Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions cgo/cgo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,43 @@ func TestCGo(t *testing.T) {
}
}

func TestCGoPragmas(t *testing.T) {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "testdata/symbols.go", nil, parser.ParseComments)
if err != nil {
t.Fatal(err)
}
files, _, _, _, _, errs := Process([]*ast.File{f}, "testdata", "main", fset, []string{"--target=armv6m-unknown-unknown-eabi"}, "linux")
if len(errs) != 0 {
t.Fatal(errs)
}
for _, file := range files {
for _, decl := range file.Decls {
fn, ok := decl.(*ast.FuncDecl)
if !ok || fn.Name.Name != "_Cgo_variadicNoescape" {
continue
}
if fn.Body != nil {
t.Error("generated C function has a body")
}
if fn.Doc == nil {
t.Fatal("generated C function has no pragma comments")
}
var pragmas []string
for _, comment := range fn.Doc.List {
if strings.HasPrefix(comment.Text, "//go:") {
pragmas = append(pragmas, comment.Text)
}
}
if len(pragmas) != 2 || pragmas[0] != "//go:variadic" || pragmas[1] != "//go:noescape" {
t.Errorf("expected separate variadic and noescape comments, got %q", pragmas)
}
return
}
}
t.Fatal("missing generated variadicNoescape declaration")
}

func Test_cgoPackage_isEquivalentAST(t *testing.T) {
fieldA := &ast.Field{Type: &ast.BasicLit{Kind: token.STRING, Value: "a"}}
fieldB := &ast.Field{Type: &ast.BasicLit{Kind: token.STRING, Value: "b"}}
Expand Down
4 changes: 2 additions & 2 deletions cgo/libclang.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,10 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
doc = append(doc, "//go:noescape")
f.noescapingFuncs[name].used = true
}
if len(doc) != 0 {
for _, text := range doc {
decl.Doc.List = append(decl.Doc.List, &ast.Comment{
Slash: pos - 1,
Text: strings.Join(doc, "\n"),
Text: text,
})
}
for i := range numArgs {
Expand Down
3 changes: 3 additions & 0 deletions cgo/testdata/symbols.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package main
int foo(int a, int b);
void variadic0();
void variadic2(int x, int y, ...);
void variadicNoescape(int *a, ...);
static void staticfunc(int x);

// Global variable signatures.
Expand All @@ -13,6 +14,7 @@ extern int someValue;
void notEscapingFunction(int *a);

#cgo noescape notEscapingFunction
#cgo noescape variadicNoescape
*/
import "C"

Expand All @@ -21,6 +23,7 @@ func accessFunctions() {
C.foo(3, 4)
C.variadic0()
C.variadic2(3, 5)
C.variadicNoescape(nil)
C.staticfunc(3)
C.notEscapingFunction(nil)
}
Expand Down
7 changes: 7 additions & 0 deletions cgo/testdata/symbols.out.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ func _Cgo_variadic2(x _Cgo_int, y _Cgo_int)

var _Cgo_variadic2$funcaddr unsafe.Pointer

//export variadicNoescape
//go:variadic
//go:noescape
func _Cgo_variadicNoescape(a *_Cgo_int)

var _Cgo_variadicNoescape$funcaddr unsafe.Pointer

//export _Cgo_static_173c95a79b6df1980521_staticfunc
func _Cgo_staticfunc!symbols.go(x _Cgo_int)

Expand Down
24 changes: 24 additions & 0 deletions compiler/compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"testing"

"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/compiler/llvmutil"
"github.com/tinygo-org/tinygo/goenv"
"github.com/tinygo-org/tinygo/loader"
"github.com/tinygo-org/tinygo/transform"
Expand Down Expand Up @@ -156,6 +157,29 @@ func TestCGoGlobalOrder(t *testing.T) {
}
}

func TestCGoPragmas(t *testing.T) {
mod, errs := testCompilePackage(t, &compileopts.Options{Target: "wasm"}, "cgo-pragmas.go")
if len(errs) != 0 {
t.Fatal(errs)
}
defer mod.Dispose()

fn := mod.NamedFunction("variadicNoescape")
if fn.IsNil() {
t.Fatal("missing variadicNoescape declaration")
}
if !fn.GlobalValueType().IsFunctionVarArg() {
t.Error("C function declaration is not variadic")
}
nocapture := fn.GetEnumAttributeAtIndex(1, llvm.AttributeKindID(llvmutil.NoCaptureAttrName()))
if !llvmutil.IsNoCapture(nocapture) {
t.Error("C function pointer parameter can escape")
}
if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil {
t.Fatal(err)
}
}

func TestOptimizedLargeAggregateABI(t *testing.T) {
options := &compileopts.Options{Target: "wasm"}
mod, errs := testCompilePackage(t, options, "large-optimized.go")
Expand Down
11 changes: 11 additions & 0 deletions compiler/testdata/cgo-pragmas.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

/*
void variadicNoescape(int *a, ...);
#cgo noescape variadicNoescape
*/
import "C"

func callVariadicNoescape(a *C.int) {
C.variadicNoescape(a)
}
Loading