mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-09 05:23:40 +00:00
compiler: support file-level //go:linkname directives
Modern golang.org/x/sys/unix (v0.36+) declares its linknames
detached from function declarations, e.g.:
func syscall_syscall(...)
//go:linkname syscall_syscall syscall.syscall
TinyGo's pragma parser only inspected function doc comments and
therefore missed these, producing link errors like:
undefined symbol: _golang.org/x/sys/unix.syscall_syscall
Extend parsePragmas to also walk the enclosing *ast.File's
free-standing comments for //go:linkname directives matching the
function's name. Function-attached directives still take
precedence. The existing 'unsafe' import gate is preserved.
Fixes #4395, #5365
This commit is contained in:
Vendored
+28
@@ -120,3 +120,31 @@ func stillEscapes(a *int, b []int, c chan int, d *[0]byte) {
|
||||
func doesHeapAlloc() *int {
|
||||
return new(int)
|
||||
}
|
||||
|
||||
// Define a function in a different package using a file-level go:linkname.
|
||||
// (Same as withLinkageName1, but with the //go:linkname directive detached
|
||||
// from the function declaration — see https://github.com/tinygo-org/tinygo/issues/4395)
|
||||
func withFileLevelLinkageName1() {
|
||||
}
|
||||
|
||||
// Import a function from a different package using a file-level go:linkname.
|
||||
// (Same as withLinkageName2, but with the //go:linkname directive detached
|
||||
// from the function declaration.)
|
||||
func withFileLevelLinkageName2()
|
||||
|
||||
//go:linkname withFileLevelLinkageName1 somepkg.someFileLevelFunction1
|
||||
//go:linkname withFileLevelLinkageName2 somepkg.someFileLevelFunction2
|
||||
|
||||
// File-level linkname directives can also appear between two function
|
||||
// declarations, in which case Go's AST attaches them as the doc comment
|
||||
// of the following function — even when the directive's localname refers
|
||||
// to a different function. Exercise that case: the directive below names
|
||||
// withAdjacentLinkageName, but Go will attach it to
|
||||
// sentinelAfterAdjacentLinkname's Doc. The file-level scan must find it
|
||||
// by walking comment groups regardless of which decl they're attached to.
|
||||
func withAdjacentLinkageName() {
|
||||
}
|
||||
|
||||
//go:linkname withAdjacentLinkageName somepkg.someAdjacentFunction
|
||||
func sentinelAfterAdjacentLinkname() {
|
||||
}
|
||||
|
||||
Vendored
+20
@@ -102,6 +102,26 @@ entry:
|
||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||
declare noalias nonnull ptr @runtime.alloc_noheap(i32, ptr, ptr) #9
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @somepkg.someFileLevelFunction1(ptr %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @somepkg.someFileLevelFunction2(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @somepkg.someAdjacentFunction(ptr %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.sentinelAfterAdjacentLinkname(ptr %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
attributes #0 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
||||
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-export-name"="extern_func" }
|
||||
|
||||
Reference in New Issue
Block a user