Compare commits
39 Commits
xgopilot/c
...
xgopilot/c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
940c6f7625 | ||
|
|
3348b645af | ||
|
|
6c85cf7594 | ||
|
|
f3e5ad536d | ||
|
|
c0a3a19294 | ||
|
|
c36ccfd9a1 | ||
|
|
060a2dea06 | ||
|
|
86cafff113 | ||
|
|
3c88949557 | ||
|
|
533ba9ebd8 | ||
|
|
f34062166b | ||
|
|
c036243b3f | ||
|
|
e16fc69ce3 | ||
|
|
a2c81327ea | ||
|
|
a74ca940e2 | ||
|
|
0c68ae00c9 | ||
|
|
8d6d1b76f2 | ||
|
|
e47728b053 | ||
|
|
9b397725da | ||
|
|
420ad8e010 | ||
|
|
6e41cc702f | ||
|
|
0a94a54772 | ||
|
|
d09ce613c8 | ||
|
|
e614edfab4 | ||
|
|
29504f2560 | ||
|
|
ee49fad4a4 | ||
|
|
946a4bf990 | ||
|
|
8b61831b0d | ||
|
|
e96625cf07 | ||
|
|
8ac7ada7f9 | ||
|
|
0b00e06185 | ||
|
|
c4fdb1edc0 | ||
|
|
224e3b9440 | ||
|
|
7fbcc8cd10 | ||
|
|
938f883be9 | ||
|
|
d145967c35 | ||
|
|
2e0fc5fb7f | ||
|
|
d8cf93a6cd | ||
|
|
01ada11b74 |
117
.github/workflows/export_test.sh
vendored
Executable file
117
.github/workflows/export_test.sh
vendored
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test script for //export with different symbol names
|
||||
# This is essential for embedded development where hardware specifications require
|
||||
# specific symbol names (e.g., ARM Cortex-M interrupt handlers).
|
||||
|
||||
set -e # Exit on any error
|
||||
|
||||
# Use current working directory (workflow already cd's to the test directory)
|
||||
WORK_DIR="$(pwd)"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Check if llgo command is available
|
||||
if ! command -v llgo &> /dev/null; then
|
||||
print_error "llgo command not found, please install llgo first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if LLGO_ROOT is set
|
||||
if [[ -z "$LLGO_ROOT" ]]; then
|
||||
print_error "LLGO_ROOT environment variable is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Starting export symbol name test..."
|
||||
print_status "Working directory: $WORK_DIR"
|
||||
print_status "LLGO_ROOT: $LLGO_ROOT"
|
||||
|
||||
echo ""
|
||||
|
||||
# Build the test program
|
||||
print_status "=== Building test program ==="
|
||||
if llgo build -o test_export main.go; then
|
||||
print_status "Build succeeded"
|
||||
else
|
||||
print_error "Build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for expected symbols using nm
|
||||
print_status "=== Checking exported symbols with nm ==="
|
||||
if ! command -v nm &> /dev/null; then
|
||||
print_error "nm command not found, skipping symbol verification"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NM_OUTPUT=$(nm test_export)
|
||||
|
||||
# Verify LPSPI2_IRQHandler symbol exists (not interruptLPSPI2)
|
||||
if echo "$NM_OUTPUT" | grep -q "LPSPI2_IRQHandler"; then
|
||||
print_status "✓ Symbol LPSPI2_IRQHandler found"
|
||||
else
|
||||
print_error "✗ Symbol LPSPI2_IRQHandler not found"
|
||||
echo "Available symbols:"
|
||||
echo "$NM_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify SysTick_Handler symbol exists (not systemTickHandler)
|
||||
if echo "$NM_OUTPUT" | grep -q "SysTick_Handler"; then
|
||||
print_status "✓ Symbol SysTick_Handler found"
|
||||
else
|
||||
print_error "✗ Symbol SysTick_Handler not found"
|
||||
echo "Available symbols:"
|
||||
echo "$NM_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify Add symbol exists (same name)
|
||||
if echo "$NM_OUTPUT" | grep -q "Add"; then
|
||||
print_status "✓ Symbol Add found"
|
||||
else
|
||||
print_error "✗ Symbol Add not found"
|
||||
echo "Available symbols:"
|
||||
echo "$NM_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify that the original function names are NOT exported as main symbols
|
||||
# (they should only appear as internal symbols, not as exported text symbols 'T')
|
||||
EXPORTED_SYMBOLS=$(echo "$NM_OUTPUT" | grep " T " || true)
|
||||
|
||||
if echo "$EXPORTED_SYMBOLS" | grep -q "interruptLPSPI2"; then
|
||||
print_error "✗ Unexpected exported symbol: interruptLPSPI2 (should be LPSPI2_IRQHandler)"
|
||||
exit 1
|
||||
else
|
||||
print_status "✓ interruptLPSPI2 not exported as main symbol"
|
||||
fi
|
||||
|
||||
if echo "$EXPORTED_SYMBOLS" | grep -q "systemTickHandler"; then
|
||||
print_error "✗ Unexpected exported symbol: systemTickHandler (should be SysTick_Handler)"
|
||||
exit 1
|
||||
else
|
||||
print_status "✓ systemTickHandler not exported as main symbol"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
print_status "=== All symbol name tests passed! ==="
|
||||
|
||||
# Cleanup
|
||||
rm -f test_export
|
||||
|
||||
print_status "Export symbol name test completed successfully!"
|
||||
101
.github/workflows/export_test_normal.sh
vendored
Normal file
101
.github/workflows/export_test_normal.sh
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test script for //export on normal (non-baremetal) targets
|
||||
# This ensures that //export with different symbol names does NOT work on normal targets
|
||||
|
||||
set -e # Exit on any error
|
||||
|
||||
# Use current working directory (workflow already cd's to the test directory)
|
||||
WORK_DIR="$(pwd)"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Check if llgo command is available
|
||||
if ! command -v llgo &> /dev/null; then
|
||||
print_error "llgo command not found, please install llgo first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if LLGO_ROOT is set
|
||||
if [[ -z "$LLGO_ROOT" ]]; then
|
||||
print_error "LLGO_ROOT environment variable is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Starting export symbol name test for normal targets..."
|
||||
print_status "Working directory: $WORK_DIR"
|
||||
print_status "LLGO_ROOT: $LLGO_ROOT"
|
||||
|
||||
echo ""
|
||||
|
||||
# Build the test program
|
||||
print_status "=== Building test program ==="
|
||||
if llgo build -o test_export main.go; then
|
||||
print_status "Build succeeded"
|
||||
else
|
||||
print_error "Build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for expected symbols using nm
|
||||
print_status "=== Checking exported symbols with nm ==="
|
||||
if ! command -v nm &> /dev/null; then
|
||||
print_error "nm command not found, skipping symbol verification"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NM_OUTPUT=$(nm test_export)
|
||||
|
||||
# For normal targets, //export SymbolName should export the FUNCTION NAME, not the symbol name
|
||||
# So we expect LPSPI2_IRQHandler, SysTick_Handler, Add (the function names)
|
||||
|
||||
# Verify LPSPI2_IRQHandler symbol exists (function name)
|
||||
if echo "$NM_OUTPUT" | grep -q "LPSPI2_IRQHandler"; then
|
||||
print_status "✓ Symbol LPSPI2_IRQHandler found (function name)"
|
||||
else
|
||||
print_error "✗ Symbol LPSPI2_IRQHandler not found"
|
||||
echo "Available symbols:"
|
||||
echo "$NM_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify SysTick_Handler symbol exists (function name)
|
||||
if echo "$NM_OUTPUT" | grep -q "SysTick_Handler"; then
|
||||
print_status "✓ Symbol SysTick_Handler found (function name)"
|
||||
else
|
||||
print_error "✗ Symbol SysTick_Handler not found"
|
||||
echo "Available symbols:"
|
||||
echo "$NM_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify Add symbol exists (same name)
|
||||
if echo "$NM_OUTPUT" | grep -q "Add"; then
|
||||
print_status "✓ Symbol Add found"
|
||||
else
|
||||
print_error "✗ Symbol Add not found"
|
||||
echo "Available symbols:"
|
||||
echo "$NM_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
print_status "=== All symbol name tests passed for normal targets! ==="
|
||||
|
||||
# Cleanup
|
||||
rm -f test_export
|
||||
|
||||
print_status "Export symbol name test for normal targets completed successfully!"
|
||||
18
.github/workflows/llgo.yml
vendored
18
.github/workflows/llgo.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
wget -P ./_demo/c/llama2-c https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin
|
||||
|
||||
- name: Upload model as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: llama2-model
|
||||
path: ./_demo/c/llama2-c/stories15M.bin
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
with:
|
||||
llvm-version: ${{matrix.llvm}}
|
||||
- name: Download model artifact
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: llama2-model
|
||||
path: ./_demo/c/llama2-c/
|
||||
@@ -133,6 +133,20 @@ jobs:
|
||||
chmod +x test.sh
|
||||
./test.sh
|
||||
|
||||
- name: Test export symbol names for embedded targets
|
||||
run: |
|
||||
echo "Testing //export with different symbol names for embedded development..."
|
||||
chmod +x .github/workflows/export_test.sh
|
||||
cd _demo/embed/export
|
||||
bash ../../../.github/workflows/export_test.sh
|
||||
|
||||
- name: Test export symbol names for normal targets
|
||||
run: |
|
||||
echo "Testing //export behavior for normal (non-embedded) targets..."
|
||||
chmod +x .github/workflows/export_test_normal.sh
|
||||
cd _demo/normal/export
|
||||
bash ../../../.github/workflows/export_test_normal.sh
|
||||
|
||||
- name: _xtool build tests
|
||||
run: |
|
||||
cd _xtool
|
||||
|
||||
12
.github/workflows/release-build.yml
vendored
12
.github/workflows/release-build.yml
vendored
@@ -82,7 +82,7 @@ jobs:
|
||||
release --verbose --skip=publish,nfpm,snapcraft --snapshot --clean
|
||||
|
||||
- name: Upload Darwin AMD64 Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: llgo-darwin-amd64
|
||||
path: .dist/*darwin-amd64.tar.gz
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload Darwin ARM64 Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: llgo-darwin-arm64
|
||||
path: .dist/*darwin-arm64.tar.gz
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload Linux AMD64 Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: llgo-linux-amd64
|
||||
path: .dist/*linux-amd64.tar.gz
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload Linux ARM64 Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: llgo-linux-arm64
|
||||
path: .dist/*linux-arm64.tar.gz
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload Checksums
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: llgo-checksums
|
||||
path: .dist/*checksums.txt
|
||||
@@ -158,7 +158,7 @@ jobs:
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Download Platform Artifact
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: llgo-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
path: .
|
||||
|
||||
22
_demo/embed/export/main.go
Normal file
22
_demo/embed/export/main.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
//export LPSPI2_IRQHandler
|
||||
func interruptLPSPI2() {
|
||||
println("LPSPI2 interrupt handled")
|
||||
}
|
||||
|
||||
//export SysTick_Handler
|
||||
func systemTickHandler() {
|
||||
println("System tick")
|
||||
}
|
||||
|
||||
//export Add
|
||||
func Add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func main() {
|
||||
interruptLPSPI2()
|
||||
systemTickHandler()
|
||||
println("Add(2, 3) =", Add(2, 3))
|
||||
}
|
||||
147
_demo/go/gobuild/demo.go
Normal file
147
_demo/go/gobuild/demo.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/build"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("runtime.Compiler = %q\n", runtime.Compiler)
|
||||
|
||||
// Test 1: Check build.Default context
|
||||
ctx := build.Default
|
||||
fmt.Printf("build.Default.Compiler = %q\n", ctx.Compiler)
|
||||
if ctx.Compiler != "gc" {
|
||||
panic(fmt.Sprintf("expected build.Default.Compiler to be \"gc\", got %q", ctx.Compiler))
|
||||
}
|
||||
|
||||
if len(ctx.ToolTags) == 0 {
|
||||
panic("expected build.Default.ToolTags to be non-empty")
|
||||
}
|
||||
fmt.Printf("build.Default.ToolTags = %v\n", ctx.ToolTags)
|
||||
|
||||
if len(ctx.ReleaseTags) == 0 {
|
||||
panic("expected build.Default.ReleaseTags to be non-empty")
|
||||
}
|
||||
fmt.Printf("build.Default.ReleaseTags count = %d\n", len(ctx.ReleaseTags))
|
||||
|
||||
// Validate GOOS and GOARCH are set
|
||||
if ctx.GOOS == "" {
|
||||
panic("expected build.Default.GOOS to be non-empty")
|
||||
}
|
||||
if ctx.GOARCH == "" {
|
||||
panic("expected build.Default.GOARCH to be non-empty")
|
||||
}
|
||||
fmt.Printf("build.Default.GOOS = %q, GOARCH = %q\n", ctx.GOOS, ctx.GOARCH)
|
||||
|
||||
// Test 2: Import standard library package with FindOnly
|
||||
pkg, err := build.Import("fmt", "", build.FindOnly)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("build.Import(\"fmt\") failed: %v", err))
|
||||
}
|
||||
if pkg.ImportPath != "fmt" {
|
||||
panic(fmt.Sprintf("expected ImportPath \"fmt\", got %q", pkg.ImportPath))
|
||||
}
|
||||
if !pkg.Goroot {
|
||||
panic("expected fmt package to be in GOROOT")
|
||||
}
|
||||
fmt.Printf("build.Import(\"fmt\"): ImportPath=%s, Goroot=%v\n", pkg.ImportPath, pkg.Goroot)
|
||||
|
||||
// Test 3: Import nested standard library package
|
||||
osPkg, err := build.Import("os/exec", "", build.FindOnly)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("build.Import(\"os/exec\") failed: %v", err))
|
||||
}
|
||||
if osPkg.ImportPath != "os/exec" {
|
||||
panic(fmt.Sprintf("expected ImportPath \"os/exec\", got %q", osPkg.ImportPath))
|
||||
}
|
||||
if !osPkg.Goroot {
|
||||
panic("expected os/exec package to be in GOROOT")
|
||||
}
|
||||
fmt.Printf("build.Import(\"os/exec\"): ImportPath=%s, Goroot=%v\n", osPkg.ImportPath, osPkg.Goroot)
|
||||
|
||||
// Test 4: Import internal package (should succeed with FindOnly)
|
||||
internalPkg, err := build.Import("internal/cpu", "", build.FindOnly)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("build.Import(\"internal/cpu\") failed: %v", err))
|
||||
}
|
||||
if internalPkg.ImportPath != "internal/cpu" {
|
||||
panic(fmt.Sprintf("expected ImportPath \"internal/cpu\", got %q", internalPkg.ImportPath))
|
||||
}
|
||||
fmt.Printf("build.Import(\"internal/cpu\"): ImportPath=%s\n", internalPkg.ImportPath)
|
||||
|
||||
// Test 5: Import with srcDir parameter
|
||||
runtimePkg, err := build.Import("runtime", "", build.FindOnly)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("build.Import(\"runtime\") failed: %v", err))
|
||||
}
|
||||
if runtimePkg.ImportPath != "runtime" {
|
||||
panic(fmt.Sprintf("expected ImportPath \"runtime\", got %q", runtimePkg.ImportPath))
|
||||
}
|
||||
if runtimePkg.Dir == "" {
|
||||
panic("expected runtime package Dir to be non-empty")
|
||||
}
|
||||
fmt.Printf("build.Import(\"runtime\"): ImportPath=%s, Dir exists=%v\n", runtimePkg.ImportPath, runtimePkg.Dir != "")
|
||||
|
||||
// Test 6: ImportDir with current directory
|
||||
dirPkg, err := build.ImportDir(".", build.FindOnly)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("build.ImportDir(\".\") failed: %v", err))
|
||||
}
|
||||
// Note: Name might be empty with FindOnly mode as it doesn't read source files
|
||||
fmt.Printf("build.ImportDir(\".\"): Dir=%s, ImportPath=%s\n", dirPkg.Dir, dirPkg.ImportPath)
|
||||
|
||||
// Test 7: IsLocalImport with various paths
|
||||
testCases := []struct {
|
||||
path string
|
||||
expected bool
|
||||
}{
|
||||
{"./foo", true},
|
||||
{"../bar", true},
|
||||
{"./", true},
|
||||
{"fmt", false},
|
||||
{"github.com/user/repo", false},
|
||||
{"", false},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
result := build.IsLocalImport(tc.path)
|
||||
if result != tc.expected {
|
||||
panic(fmt.Sprintf("build.IsLocalImport(%q): expected %v, got %v", tc.path, tc.expected, result))
|
||||
}
|
||||
}
|
||||
fmt.Printf("build.IsLocalImport: all test cases passed\n")
|
||||
|
||||
// Test 8: Verify Context has expected fields
|
||||
if ctx.GOPATH == "" && ctx.GOROOT == "" {
|
||||
panic("expected either GOPATH or GOROOT to be set")
|
||||
}
|
||||
fmt.Printf("build.Default.GOROOT exists = %v\n", ctx.GOROOT != "")
|
||||
|
||||
// Test 9: Import with AllowBinary flag
|
||||
binaryPkg, err := build.Import("fmt", "", build.FindOnly|build.AllowBinary)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("build.Import with AllowBinary failed: %v", err))
|
||||
}
|
||||
if binaryPkg.ImportPath != "fmt" {
|
||||
panic(fmt.Sprintf("expected ImportPath \"fmt\", got %q", binaryPkg.ImportPath))
|
||||
}
|
||||
fmt.Printf("build.Import(\"fmt\") with AllowBinary: success\n")
|
||||
|
||||
// Test 10: Verify compiler tag in build context
|
||||
hasCompilerTag := false
|
||||
for _, tag := range ctx.ReleaseTags {
|
||||
if strings.HasPrefix(tag, "go1.") {
|
||||
hasCompilerTag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasCompilerTag {
|
||||
panic("expected at least one go1.x release tag")
|
||||
}
|
||||
fmt.Printf("build.Default.ReleaseTags: contains go1.x tags = %v\n", hasCompilerTag)
|
||||
|
||||
fmt.Printf("\nSuccess! All go/build public functions work correctly with llgo\n")
|
||||
fmt.Printf("Total tests passed: 10\n")
|
||||
}
|
||||
49
_demo/go/reflectindirect/reflect-indirect.go
Normal file
49
_demo/go/reflectindirect/reflect-indirect.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func main() {
|
||||
x := 42
|
||||
p := &x
|
||||
|
||||
// Test 1: Non-pointer value - should return same value
|
||||
v1 := reflect.Indirect(reflect.ValueOf(x))
|
||||
if !v1.IsValid() || v1.Interface() != 42 {
|
||||
panic("Non-pointer test failed: expected 42")
|
||||
}
|
||||
|
||||
// Test 2: Pointer - should dereference
|
||||
v2 := reflect.Indirect(reflect.ValueOf(p))
|
||||
if !v2.IsValid() || v2.Interface() != 42 {
|
||||
panic("Pointer dereference test failed: expected 42")
|
||||
}
|
||||
|
||||
// Test 3: Nil pointer - should return invalid Value
|
||||
var nilPtr *int
|
||||
v3 := reflect.Indirect(reflect.ValueOf(nilPtr))
|
||||
if v3.IsValid() {
|
||||
panic("Nil pointer test failed: expected invalid Value")
|
||||
}
|
||||
|
||||
// Test 4: Struct value - should return same value
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
person := Person{Name: "Alice", Age: 30}
|
||||
v4 := reflect.Indirect(reflect.ValueOf(person))
|
||||
if !v4.IsValid() || v4.Interface().(Person).Name != "Alice" || v4.Interface().(Person).Age != 30 {
|
||||
panic("Struct value test failed: expected Person{Name: Alice, Age: 30}")
|
||||
}
|
||||
|
||||
// Test 5: Struct pointer - should dereference
|
||||
personPtr := &Person{Name: "Bob", Age: 25}
|
||||
v5 := reflect.Indirect(reflect.ValueOf(personPtr))
|
||||
if !v5.IsValid() || v5.Interface().(Person).Name != "Bob" || v5.Interface().(Person).Age != 25 {
|
||||
panic("Struct pointer test failed: expected Person{Name: Bob, Age: 25}")
|
||||
}
|
||||
|
||||
println("PASS")
|
||||
}
|
||||
22
_demo/normal/export/main.go
Normal file
22
_demo/normal/export/main.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
//export LPSPI2_IRQHandler
|
||||
func LPSPI2_IRQHandler() {
|
||||
println("LPSPI2 interrupt handled")
|
||||
}
|
||||
|
||||
//export SysTick_Handler
|
||||
func SysTick_Handler() {
|
||||
println("System tick")
|
||||
}
|
||||
|
||||
//export Add
|
||||
func Add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func main() {
|
||||
LPSPI2_IRQHandler()
|
||||
SysTick_Handler()
|
||||
println("Add(2, 3) =", Add(2, 3))
|
||||
}
|
||||
33
cl/import.go
33
cl/import.go
@@ -278,7 +278,8 @@ func (p *context) initLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName s
|
||||
for n := len(doc.List) - 1; n >= 0; n-- {
|
||||
line := doc.List[n].Text
|
||||
ret := p.initLinkname(line, func(name string) (_ string, _, ok bool) {
|
||||
return fullName, isVar, name == inPkgName
|
||||
// support empty name for //export directive
|
||||
return fullName, isVar, name == inPkgName || name == ""
|
||||
})
|
||||
if ret != unknownDirective {
|
||||
return ret == hasLinkname
|
||||
@@ -312,10 +313,32 @@ func (p *context) initLinkname(line string, f func(inPkgName string) (fullName s
|
||||
p.initLink(line, len(llgolink), false, f)
|
||||
return hasLinkname
|
||||
} else if strings.HasPrefix(line, export) {
|
||||
// rewrite //export FuncName to //export FuncName FuncName
|
||||
funcName := strings.TrimSpace(line[len(export):])
|
||||
line = line + " " + funcName
|
||||
p.initLink(line, len(export), true, f)
|
||||
// support //export ExportName
|
||||
// format: //export ExportName or //export FuncName ExportName
|
||||
exportName := strings.TrimSpace(line[len(export):])
|
||||
var inPkgName string
|
||||
isBaremetal := os.Getenv("LLGO_TARGET_BAREMETAL") == "1"
|
||||
if idx := strings.IndexByte(exportName, ' '); idx > 0 {
|
||||
// format: //export FuncName ExportName (go-style)
|
||||
inPkgName = exportName[:idx]
|
||||
exportName = strings.TrimLeft(exportName[idx+1:], " ")
|
||||
} else {
|
||||
// format: //export ExportName (tinygo-style, only for baremetal targets)
|
||||
if !isBaremetal {
|
||||
// For non-baremetal targets, treat as function name (standard Go behavior)
|
||||
inPkgName = exportName
|
||||
} else {
|
||||
// For baremetal targets, use empty string to match any function
|
||||
inPkgName = ""
|
||||
}
|
||||
}
|
||||
if fullName, _, ok := f(inPkgName); ok {
|
||||
p.prog.SetLinkname(fullName, exportName)
|
||||
p.pkg.SetExport(fullName, exportName)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, "==>", line)
|
||||
fmt.Fprintf(os.Stderr, "llgo: export %s not found and ignored\n", inPkgName)
|
||||
}
|
||||
return hasLinkname
|
||||
} else if strings.HasPrefix(line, directive) {
|
||||
// skip unknown annotation but continue to parse the next annotation
|
||||
|
||||
@@ -222,6 +222,13 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
||||
}
|
||||
if len(export.BuildTags) > 0 {
|
||||
tags += "," + strings.Join(export.BuildTags, ",")
|
||||
// Set environment variable if building for baremetal target
|
||||
for _, tag := range export.BuildTags {
|
||||
if tag == "baremetal" {
|
||||
os.Setenv("LLGO_TARGET_BAREMETAL", "1")
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg := &packages.Config{
|
||||
Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,
|
||||
|
||||
@@ -22,6 +22,7 @@ var hasAltPkg = map[string]none{
|
||||
"crypto/sha256": {},
|
||||
"crypto/sha512": {},
|
||||
"crypto/subtle": {},
|
||||
"go/build": {},
|
||||
"go/parser": {},
|
||||
"hash/crc32": {},
|
||||
"hash/maphash": {},
|
||||
|
||||
19
runtime/internal/lib/go/build/build.go
Normal file
19
runtime/internal/lib/go/build/build.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package build provides alternative implementations for go/build.
|
||||
// We override build.Default.Compiler in an init function.
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// LLGO PATCH: Override build.Default.Compiler to be "gc" instead of "llgo"
|
||||
// This prevents "unknown compiler" errors when user code uses go/build package
|
||||
// Even though runtime.Compiler = "llgo", we set build.Default.Compiler = "gc"
|
||||
build.Default.Compiler = "gc"
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/goplus/llgo/runtime/internal/runtime"
|
||||
)
|
||||
|
||||
// llgo:skip init CompareString
|
||||
// llgo:skip init
|
||||
type _bytealg struct{}
|
||||
|
||||
func IndexByte(b []byte, ch byte) int {
|
||||
|
||||
@@ -1759,6 +1759,16 @@ func ValueOf(i any) Value {
|
||||
return unpackEface(i)
|
||||
}
|
||||
|
||||
// Indirect returns the value that v points to.
|
||||
// If v is a nil pointer, Indirect returns a zero Value.
|
||||
// If v is not a pointer, Indirect returns v.
|
||||
func Indirect(v Value) Value {
|
||||
if v.Kind() != Pointer {
|
||||
return v
|
||||
}
|
||||
return v.Elem()
|
||||
}
|
||||
|
||||
// arrayAt returns the i-th element of p,
|
||||
// an array whose elements are eltSize bytes wide.
|
||||
// The array pointed at by p must have at least i+1 elements:
|
||||
|
||||
@@ -140,6 +140,10 @@ type Func struct {
|
||||
opaque struct{} // unexported field to disallow conversions
|
||||
}
|
||||
|
||||
func (f *Func) Name() string {
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
// moduledata records information about the layout of the executable
|
||||
// image. It is written by the linker. Any changes here must be
|
||||
// matched changes to the code in cmd/link/internal/ld/symtab.go:symtab.
|
||||
|
||||
Reference in New Issue
Block a user