mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-30 00:28:41 +00:00
6d49f0177b
Go 1.27 introduced the //go:linknamestd directive, a standard-library variant of //go:linkname that does not require importing "unsafe". The iter package switched to it for referencing runtime.newcoro and runtime.coroswitch, which caused "linker could not find symbol iter.newcoro / iter.coroswitch" errors when building with Go 1.27. Handle //go:linknamestd the same as //go:linkname, bypassing the unsafe import requirement, and add test coverage in the pragma compiler test. Signed-off-by: deadprogram <ron@hybridgroup.com>
157 lines
3.9 KiB
Go
157 lines
3.9 KiB
Go
package main
|
|
|
|
import _ "unsafe"
|
|
|
|
// Creates an external global with name extern_global.
|
|
//
|
|
//go:extern extern_global
|
|
var externGlobal [0]byte
|
|
|
|
// Creates a
|
|
//
|
|
//go:align 32
|
|
var alignedGlobal [4]uint32
|
|
|
|
// Test conflicting pragmas (the last one counts).
|
|
//
|
|
//go:align 64
|
|
//go:align 16
|
|
var alignedGlobal16 [4]uint32
|
|
|
|
// Test exported functions.
|
|
//
|
|
//export extern_func
|
|
func externFunc() {
|
|
}
|
|
|
|
// Define a function in a different package using go:linkname.
|
|
//
|
|
//go:linkname withLinkageName1 somepkg.someFunction1
|
|
func withLinkageName1() {
|
|
}
|
|
|
|
// Import a function from a different package using go:linkname.
|
|
//
|
|
//go:linkname withLinkageName2 somepkg.someFunction2
|
|
func withLinkageName2()
|
|
|
|
// Import a function from a different package using go:linknamestd (the standard
|
|
// library variant of go:linkname introduced in Go 1.27).
|
|
//
|
|
//go:linknamestd withLinkageNameStd somepkg.someFunctionStd
|
|
func withLinkageNameStd()
|
|
|
|
// Function has an 'inline hint', similar to the inline keyword in C.
|
|
//
|
|
//go:inline
|
|
func inlineFunc() {
|
|
}
|
|
|
|
// Function should never be inlined, equivalent to GCC
|
|
// __attribute__((noinline)).
|
|
//
|
|
//go:noinline
|
|
func noinlineFunc() {
|
|
}
|
|
|
|
type Int interface {
|
|
int8 | int16
|
|
}
|
|
|
|
// Same for generic functions (but the compiler may miss the pragma due to it
|
|
// being generic).
|
|
//
|
|
//go:noinline
|
|
func noinlineGenericFunc[T Int]() {
|
|
}
|
|
|
|
func useGeneric() {
|
|
// Make sure the generic function above is instantiated.
|
|
noinlineGenericFunc[int8]()
|
|
}
|
|
|
|
// This function should have the specified section.
|
|
//
|
|
//go:section .special_function_section
|
|
func functionInSection() {
|
|
}
|
|
|
|
//export exportedFunctionInSection
|
|
//go:section .special_function_section
|
|
func exportedFunctionInSection() {
|
|
}
|
|
|
|
//go:wasmimport modulename import1
|
|
func declaredImport()
|
|
|
|
// Legacy way of importing a function.
|
|
//
|
|
//go:wasm-module foobar
|
|
//export imported
|
|
func foobarImport()
|
|
|
|
// The wasm-module pragma is not functional here, but it should be safe.
|
|
//
|
|
//go:wasm-module foobar
|
|
//export exported
|
|
func foobarExportModule() {
|
|
}
|
|
|
|
// This function should not: it's only a declaration and not a definition.
|
|
//
|
|
//go:section .special_function_section
|
|
func undefinedFunctionNotInSection()
|
|
|
|
//go:section .special_global_section
|
|
var globalInSection uint32
|
|
|
|
//go:section .special_global_section
|
|
//go:extern undefinedGlobalNotInSection
|
|
var undefinedGlobalNotInSection uint32
|
|
|
|
//go:align 1024
|
|
//go:section .global_section
|
|
var multipleGlobalPragmas uint32
|
|
|
|
//go:noescape
|
|
func doesNotEscapeParam(a *int, b []int, c chan int, d *[0]byte)
|
|
|
|
// The //go:noescape pragma only works on declarations, not definitions.
|
|
//
|
|
//go:noescape
|
|
func stillEscapes(a *int, b []int, c chan int, d *[0]byte) {
|
|
}
|
|
|
|
//go:noheap
|
|
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() {
|
|
}
|