cl,build: support //export with different names on embedded targets
Add support for using different C symbol names in //export directives
when compiling for embedded targets (enabled via -target flag).
This is for TinyGo compatibility on embedded platforms where hardware
interrupt handlers often require specific naming conventions.
Implementation:
- Add EnableExportRename() to control export rename behavior
- Add isExport parameter to initLink callback for context awareness
- Update initLinknameByDoc() to handle export rename logic:
* When isExport && enableExportRename: allow different names
* Otherwise: require name match
- Clean error handling in initLink():
* export + enableExportRename: silent return (already processed)
* export + !enableExportRename: panic with clear error message
* other cases: warning for missing linkname
Example:
//export LPSPI2_IRQHandler
func interruptLPSPI2() { ... }
The Go function is named interruptLPSPI2 but exported as
LPSPI2_IRQHandler for the hardware vector table.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,11 @@ var (
|
|||||||
enableDbg bool
|
enableDbg bool
|
||||||
enableDbgSyms bool
|
enableDbgSyms bool
|
||||||
disableInline bool
|
disableInline bool
|
||||||
|
|
||||||
|
// enableExportRename enables //export to use different C symbol names than Go function names.
|
||||||
|
// This is for TinyGo compatibility when using -target flag for embedded targets.
|
||||||
|
// Currently, using -target implies TinyGo embedded target mode.
|
||||||
|
enableExportRename bool
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetDebug sets debug flags.
|
// SetDebug sets debug flags.
|
||||||
@@ -73,6 +78,12 @@ func EnableTrace(b bool) {
|
|||||||
enableCallTracing = b
|
enableCallTracing = b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableExportRename enables or disables //export with different C symbol names.
|
||||||
|
// This is enabled when using -target flag for TinyGo compatibility.
|
||||||
|
func EnableExportRename(b bool) {
|
||||||
|
enableExportRename = b
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type instrOrValue interface {
|
type instrOrValue interface {
|
||||||
|
|||||||
19
cl/import.go
19
cl/import.go
@@ -73,7 +73,7 @@ func (p *pkgSymInfo) initLinknames(ctx *context) {
|
|||||||
lines := bytes.Split(b, sep)
|
lines := bytes.Split(b, sep)
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
if bytes.HasPrefix(line, commentPrefix) {
|
if bytes.HasPrefix(line, commentPrefix) {
|
||||||
ctx.initLinkname(string(line), func(inPkgName string) (fullName string, isVar, ok bool) {
|
ctx.initLinkname(string(line), func(inPkgName string, isExport bool) (fullName string, isVar, ok bool) {
|
||||||
if sym, ok := p.syms[inPkgName]; ok && file == sym.file {
|
if sym, ok := p.syms[inPkgName]; ok && file == sym.file {
|
||||||
return sym.fullName, sym.isVar, true
|
return sym.fullName, sym.isVar, true
|
||||||
}
|
}
|
||||||
@@ -277,8 +277,8 @@ func (p *context) initLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName s
|
|||||||
if doc != nil {
|
if doc != nil {
|
||||||
for n := len(doc.List) - 1; n >= 0; n-- {
|
for n := len(doc.List) - 1; n >= 0; n-- {
|
||||||
line := doc.List[n].Text
|
line := doc.List[n].Text
|
||||||
ret := p.initLinkname(line, func(name string) (_ string, _, ok bool) {
|
ret := p.initLinkname(line, func(name string, isExport bool) (_ string, _, ok bool) {
|
||||||
return fullName, isVar, name == inPkgName
|
return fullName, isVar, name == inPkgName || (isExport && enableExportRename)
|
||||||
})
|
})
|
||||||
if ret != unknownDirective {
|
if ret != unknownDirective {
|
||||||
return ret == hasLinkname
|
return ret == hasLinkname
|
||||||
@@ -294,7 +294,7 @@ const (
|
|||||||
unknownDirective = -1
|
unknownDirective = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) initLinkname(line string, f func(inPkgName string) (fullName string, isVar, ok bool)) int {
|
func (p *context) initLinkname(line string, f func(inPkgName string, isExport bool) (fullName string, isVar, ok bool)) int {
|
||||||
const (
|
const (
|
||||||
linkname = "//go:linkname "
|
linkname = "//go:linkname "
|
||||||
llgolink = "//llgo:link "
|
llgolink = "//llgo:link "
|
||||||
@@ -324,17 +324,24 @@ func (p *context) initLinkname(line string, f func(inPkgName string) (fullName s
|
|||||||
return noDirective
|
return noDirective
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initLink(line string, prefix int, export bool, f func(inPkgName string) (fullName string, isVar, ok bool)) {
|
func (p *context) initLink(line string, prefix int, export bool, f func(inPkgName string, isExport bool) (fullName string, isVar, ok bool)) {
|
||||||
text := strings.TrimSpace(line[prefix:])
|
text := strings.TrimSpace(line[prefix:])
|
||||||
if idx := strings.IndexByte(text, ' '); idx > 0 {
|
if idx := strings.IndexByte(text, ' '); idx > 0 {
|
||||||
inPkgName := text[:idx]
|
inPkgName := text[:idx]
|
||||||
if fullName, _, ok := f(inPkgName); ok {
|
if fullName, _, ok := f(inPkgName, export); ok {
|
||||||
link := strings.TrimLeft(text[idx+1:], " ")
|
link := strings.TrimLeft(text[idx+1:], " ")
|
||||||
p.prog.SetLinkname(fullName, link)
|
p.prog.SetLinkname(fullName, link)
|
||||||
if export {
|
if export {
|
||||||
p.pkg.SetExport(fullName, link)
|
p.pkg.SetExport(fullName, link)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Export with different names already processed by initLinknameByDoc
|
||||||
|
if export && enableExportRename {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if export {
|
||||||
|
panic(fmt.Sprintf("export comment has wrong name %q", inPkgName))
|
||||||
|
}
|
||||||
fmt.Fprintln(os.Stderr, "==>", line)
|
fmt.Fprintln(os.Stderr, "==>", line)
|
||||||
fmt.Fprintf(os.Stderr, "llgo: linkname %s not found and ignored\n", inPkgName)
|
fmt.Fprintf(os.Stderr, "llgo: linkname %s not found and ignored\n", inPkgName)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,6 +214,11 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
conf.Goarch = export.GOARCH
|
conf.Goarch = export.GOARCH
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable different export names for TinyGo compatibility when using -target
|
||||||
|
if conf.Target != "" {
|
||||||
|
cl.EnableExportRename(true)
|
||||||
|
}
|
||||||
|
|
||||||
verbose := conf.Verbose
|
verbose := conf.Verbose
|
||||||
patterns := args
|
patterns := args
|
||||||
tags := "llgo,math_big_pure_go"
|
tags := "llgo,math_big_pure_go"
|
||||||
|
|||||||
Reference in New Issue
Block a user