diff --git a/compiler/compiler.go b/compiler/compiler.go index 925b61bf..a34d9848 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -715,11 +715,11 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package member := pkg.Members[name] switch member := member.(type) { case *ssa.Function: + // Create the function definition. + b := newBuilder(c, irbuilder, member) if member.Blocks == nil { continue // external function } - // Create the function definition. - b := newBuilder(c, irbuilder, member) b.createFunction() case *ssa.Type: if types.IsInterface(member.Type()) { @@ -758,8 +758,8 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package case *ssa.Global: // Global variable. info := c.getGlobalInfo(member) + global := c.getGlobal(member) if !info.extern { - global := c.getGlobal(member) global.SetInitializer(llvm.ConstNull(global.Type().ElementType())) global.SetVisibility(llvm.HiddenVisibility) } diff --git a/compiler/compiler_test.go b/compiler/compiler_test.go index 4149e149..45d5b8c3 100644 --- a/compiler/compiler_test.go +++ b/compiler/compiler_test.go @@ -45,6 +45,7 @@ func TestCompiler(t *testing.T) { {"float.go", ""}, {"interface.go", ""}, {"func.go", ""}, + {"pragma.go", ""}, {"goroutine.go", "wasm"}, {"goroutine.go", "cortex-m-qemu"}, } diff --git a/compiler/testdata/pragma.go b/compiler/testdata/pragma.go new file mode 100644 index 00000000..505e78a9 --- /dev/null +++ b/compiler/testdata/pragma.go @@ -0,0 +1,41 @@ +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() + +// 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() { +} diff --git a/compiler/testdata/pragma.ll b/compiler/testdata/pragma.ll new file mode 100644 index 00000000..0fdc753e --- /dev/null +++ b/compiler/testdata/pragma.ll @@ -0,0 +1,43 @@ +; ModuleID = 'pragma.go' +source_filename = "pragma.go" +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32--wasi" + +@extern_global = external global [0 x i8], align 1 +@main.alignedGlobal = hidden global [4 x i32] zeroinitializer, align 32 +@main.alignedGlobal16 = hidden global [4 x i32] zeroinitializer, align 16 + +declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) + +define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr { +entry: + ret void +} + +define void @extern_func() #0 { +entry: + ret void +} + +define hidden void @somepkg.someFunction1(i8* %context, i8* %parentHandle) unnamed_addr { +entry: + ret void +} + +declare void @somepkg.someFunction2(i8*, i8*) + +; Function Attrs: inlinehint +define hidden void @main.inlineFunc(i8* %context, i8* %parentHandle) unnamed_addr #1 { +entry: + ret void +} + +; Function Attrs: noinline +define hidden void @main.noinlineFunc(i8* %context, i8* %parentHandle) unnamed_addr #2 { +entry: + ret void +} + +attributes #0 = { "wasm-export-name"="extern_func" } +attributes #1 = { inlinehint } +attributes #2 = { noinline }