diff --git a/_demo/embedded/export_test/main.go b/_demo/embedded/export_test/main.go new file mode 100644 index 00000000..ec29c390 --- /dev/null +++ b/_demo/embedded/export_test/main.go @@ -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)) +} diff --git a/_demo/embedded/export_test/test.sh b/_demo/embedded/export_test/test.sh new file mode 100755 index 00000000..402850bb --- /dev/null +++ b/_demo/embedded/export_test/test.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -e + +echo "Testing //export with different symbol names..." + +# Set LLGO_ROOT to repository root +export LLGO_ROOT=/workspace + +# Build the test program +echo "Building test program..." +/workspace/llgo build -o test_export main.go || exit 1 + +# Check for expected symbols using nm +echo "Verifying symbols with nm..." + +# Should find LPSPI2_IRQHandler (not interruptLPSPI2) +if nm test_export | grep -q "T LPSPI2_IRQHandler"; then + echo "✓ Symbol LPSPI2_IRQHandler found" +else + echo "✗ Symbol LPSPI2_IRQHandler not found" + echo "Available symbols:" + nm test_export | grep " T " + exit 1 +fi + +# Should find SysTick_Handler (not systemTickHandler) +if nm test_export | grep -q "T SysTick_Handler"; then + echo "✓ Symbol SysTick_Handler found" +else + echo "✗ Symbol SysTick_Handler not found" + exit 1 +fi + +# Should find Add (same name) +if nm test_export | grep -q "T Add"; then + echo "✓ Symbol Add found" +else + echo "✗ Symbol Add not found" + exit 1 +fi + +echo "" +echo "All symbol checks passed! ✓" diff --git a/cl/import.go b/cl/import.go index ea472819..9cae2f68 100644 --- a/cl/import.go +++ b/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,26 @@ 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 + 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) + // 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