From 6c80c40bbbf5441418846f2a0a8a0183175efff9 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 16 Feb 2025 14:29:32 +0100 Subject: [PATCH 01/10] cgo: mangle identifier names This mangles CGo identifier names to something like "_Cgo_foo" instead of using literal identifiers like "C.foo". This works around https://github.com/golang/go/issues/71777. I don't like this solution, but I hope we'll find a better solution in the future. In that case we can revert this commit. --- cgo/cgo.go | 109 ++++++++----------- cgo/libclang.go | 54 +++++----- cgo/testdata/basic.out.go | 62 +++++------ cgo/testdata/const.out.go | 76 ++++++------- cgo/testdata/errors.out.go | 92 ++++++++-------- cgo/testdata/flags.out.go | 66 ++++++------ cgo/testdata/symbols.out.go | 84 +++++++-------- cgo/testdata/types.out.go | 210 ++++++++++++++++++------------------ compiler/symbol.go | 5 +- 9 files changed, 371 insertions(+), 387 deletions(-) diff --git a/cgo/cgo.go b/cgo/cgo.go index cb822a38ec..6b8ea4373d 100644 --- a/cgo/cgo.go +++ b/cgo/cgo.go @@ -92,18 +92,18 @@ type noescapingFunc struct { // cgoAliases list type aliases between Go and C, for types that are equivalent // in both languages. See addTypeAliases. var cgoAliases = map[string]string{ - "C.int8_t": "int8", - "C.int16_t": "int16", - "C.int32_t": "int32", - "C.int64_t": "int64", - "C.uint8_t": "uint8", - "C.uint16_t": "uint16", - "C.uint32_t": "uint32", - "C.uint64_t": "uint64", - "C.uintptr_t": "uintptr", - "C.float": "float32", - "C.double": "float64", - "C._Bool": "bool", + "_Cgo_int8_t": "int8", + "_Cgo_int16_t": "int16", + "_Cgo_int32_t": "int32", + "_Cgo_int64_t": "int64", + "_Cgo_uint8_t": "uint8", + "_Cgo_uint16_t": "uint16", + "_Cgo_uint32_t": "uint32", + "_Cgo_uint64_t": "uint64", + "_Cgo_uintptr_t": "uintptr", + "_Cgo_float": "float32", + "_Cgo_double": "float64", + "_Cgo__Bool": "bool", } // builtinAliases are handled specially because they only exist on the Go side @@ -145,48 +145,46 @@ typedef unsigned long long _Cgo_ulonglong; // The string/bytes functions below implement C.CString etc. To make sure the // runtime doesn't need to know the C int type, lengths are converted to uintptr // first. -// These functions will be modified to get a "C." prefix, so the source below -// doesn't reflect the final AST. const generatedGoFilePrefixBase = ` import "syscall" import "unsafe" var _ unsafe.Pointer -//go:linkname C.CString runtime.cgo_CString -func CString(string) *C.char +//go:linkname _Cgo_CString runtime.cgo_CString +func _Cgo_CString(string) *_Cgo_char -//go:linkname C.GoString runtime.cgo_GoString -func GoString(*C.char) string +//go:linkname _Cgo_GoString runtime.cgo_GoString +func _Cgo_GoString(*_Cgo_char) string -//go:linkname C.__GoStringN runtime.cgo_GoStringN -func __GoStringN(*C.char, uintptr) string +//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN +func _Cgo___GoStringN(*_Cgo_char, uintptr) string -func GoStringN(cstr *C.char, length C.int) string { - return C.__GoStringN(cstr, uintptr(length)) +func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string { + return _Cgo___GoStringN(cstr, uintptr(length)) } -//go:linkname C.__GoBytes runtime.cgo_GoBytes -func __GoBytes(unsafe.Pointer, uintptr) []byte +//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes +func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte -func GoBytes(ptr unsafe.Pointer, length C.int) []byte { - return C.__GoBytes(ptr, uintptr(length)) +func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte { + return _Cgo___GoBytes(ptr, uintptr(length)) } -//go:linkname C.__CBytes runtime.cgo_CBytes -func __CBytes([]byte) unsafe.Pointer +//go:linkname _Cgo___CBytes runtime.cgo_CBytes +func _Cgo___CBytes([]byte) unsafe.Pointer -func CBytes(b []byte) unsafe.Pointer { - return C.__CBytes(b) +func _Cgo_CBytes(b []byte) unsafe.Pointer { + return _Cgo___CBytes(b) } -//go:linkname C.__get_errno_num runtime.cgo_errno -func __get_errno_num() uintptr +//go:linkname _Cgo___get_errno_num runtime.cgo_errno +func _Cgo___get_errno_num() uintptr ` const generatedGoFilePrefixOther = generatedGoFilePrefixBase + ` -func __get_errno() error { - return syscall.Errno(C.__get_errno_num()) +func _Cgo___get_errno() error { + return syscall.Errno(_Cgo___get_errno_num()) } ` @@ -197,7 +195,7 @@ func __get_errno() error { // map the errno values to match the values in the syscall package. // Source of the errno values: lib/mingw-w64/mingw-w64-headers/crt/errno.h const generatedGoFilePrefixWindows = generatedGoFilePrefixBase + ` -var __errno_mapping = [...]syscall.Errno{ +var _Cgo___errno_mapping = [...]syscall.Errno{ 1: syscall.EPERM, 2: syscall.ENOENT, 3: syscall.ESRCH, @@ -238,10 +236,10 @@ var __errno_mapping = [...]syscall.Errno{ 42: syscall.EILSEQ, } -func __get_errno() error { - num := C.__get_errno_num() - if num < uintptr(len(__errno_mapping)) { - if mapped := __errno_mapping[num]; mapped != 0 { +func _Cgo___get_errno() error { + num := _Cgo___get_errno_num() + if num < uintptr(len(_Cgo___errno_mapping)) { + if mapped := _Cgo___errno_mapping[num]; mapped != 0 { return mapped } } @@ -304,23 +302,6 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl // If the Comments field is not set to nil, the go/format package will get // confused about where comments should go. p.generated.Comments = nil - // Adjust some of the functions in there. - for _, decl := range p.generated.Decls { - switch decl := decl.(type) { - case *ast.FuncDecl: - switch decl.Name.Name { - case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes", "CBytes", "__CBytes", "__get_errno_num", "__get_errno", "__errno_mapping": - // Adjust the name to have a "C." prefix so it is correctly - // resolved. - decl.Name.Name = "C." + decl.Name.Name - } - } - } - // Patch some types, for example *C.char in C.CString. - cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker - astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool { - return cf.walker(cursor, nil) - }, nil) // Find `import "C"` C fragments in the file. p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file @@ -399,7 +380,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl Tok: token.TYPE, } for _, name := range builtinAliases { - typeSpec := p.getIntegerType("C."+name, names["_Cgo_"+name]) + typeSpec := p.getIntegerType("_Cgo_"+name, names["_Cgo_"+name]) gen.Specs = append(gen.Specs, typeSpec) } p.generated.Decls = append(p.generated.Decls, gen) @@ -1272,7 +1253,7 @@ func (p *cgoPackage) getUnnamedDeclName(prefix string, itf interface{}) string { func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) string { // Some types are defined in stdint.h and map directly to a particular Go // type. - if alias := cgoAliases["C."+name]; alias != "" { + if alias := cgoAliases["_Cgo_"+name]; alias != "" { return alias } node := f.getASTDeclNode(name, found) @@ -1282,7 +1263,7 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st } return node.Name.Name } - return "C." + name + return "_Cgo_" + name } // getASTDeclNode will declare the given C AST node (if not already defined) and @@ -1382,8 +1363,8 @@ extern __typeof(%s) %s __attribute__((alias(%#v))); case *elaboratedTypeInfo: // Add struct bitfields. for _, bitfield := range elaboratedType.bitfields { - f.createBitfieldGetter(bitfield, "C."+name) - f.createBitfieldSetter(bitfield, "C."+name) + f.createBitfieldGetter(bitfield, "_Cgo_"+name) + f.createBitfieldSetter(bitfield, "_Cgo_"+name) } if elaboratedType.unionSize != 0 { // Create union getters/setters. @@ -1392,7 +1373,7 @@ extern __typeof(%s) %s __attribute__((alias(%#v))); f.addError(elaboratedType.pos, fmt.Sprintf("union must have field with a single name, it has %d names", len(field.Names))) continue } - f.createUnionAccessor(field, "C."+name) + f.createUnionAccessor(field, "_Cgo_"+name) } } } @@ -1441,7 +1422,7 @@ func (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) b node.Rhs = append(node.Rhs, &ast.CallExpr{ Fun: &ast.Ident{ NamePos: node.Lhs[1].End(), - Name: "C.__get_errno", + Name: "_Cgo___get_errno", }, }) } @@ -1466,7 +1447,7 @@ func (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) b return true } if x.Name == "C" { - name := "C." + node.Sel.Name + name := "_Cgo_" + node.Sel.Name if found, ok := names[node.Sel.Name]; ok { name = f.getASTDeclName(node.Sel.Name, found, false) } diff --git a/cgo/libclang.go b/cgo/libclang.go index 4da77ff6e7..759417a6ea 100644 --- a/cgo/libclang.go +++ b/cgo/libclang.go @@ -219,7 +219,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { numArgs := int(C.tinygo_clang_Cursor_getNumArguments(c)) obj := &ast.Object{ Kind: ast.Fun, - Name: "C." + name, + Name: "_Cgo_" + name, } exportName := name localName := name @@ -257,7 +257,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { }, Name: &ast.Ident{ NamePos: pos, - Name: "C." + localName, + Name: "_Cgo_" + localName, Obj: obj, }, Type: &ast.FuncType{ @@ -319,7 +319,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { return decl, stringSignature case C.CXCursor_StructDecl, C.CXCursor_UnionDecl: typ := f.makeASTRecordType(c, pos) - typeName := "C." + name + typeName := "_Cgo_" + name typeExpr := typ.typeExpr if typ.unionSize != 0 { // Convert to a single-field struct type. @@ -340,7 +340,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { obj.Decl = typeSpec return typeSpec, typ case C.CXCursor_TypedefDecl: - typeName := "C." + name + typeName := "_Cgo_" + name underlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(c) obj := &ast.Object{ Kind: ast.Typ, @@ -378,12 +378,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { } obj := &ast.Object{ Kind: ast.Var, - Name: "C." + name, + Name: "_Cgo_" + name, } valueSpec := &ast.ValueSpec{ Names: []*ast.Ident{{ NamePos: pos, - Name: "C." + name, + Name: "_Cgo_" + name, Obj: obj, }}, Type: typeExpr, @@ -407,12 +407,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { } obj := &ast.Object{ Kind: ast.Con, - Name: "C." + name, + Name: "_Cgo_" + name, } valueSpec := &ast.ValueSpec{ Names: []*ast.Ident{{ NamePos: pos, - Name: "C." + name, + Name: "_Cgo_" + name, Obj: obj, }}, Values: []ast.Expr{expr}, @@ -423,7 +423,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { case C.CXCursor_EnumDecl: obj := &ast.Object{ Kind: ast.Typ, - Name: "C." + name, + Name: "_Cgo_" + name, } underlying := C.tinygo_clang_getEnumDeclIntegerType(c) // TODO: gc's CGo implementation uses types such as `uint32` for enums @@ -431,7 +431,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { typeSpec := &ast.TypeSpec{ Name: &ast.Ident{ NamePos: pos, - Name: "C." + name, + Name: "_Cgo_" + name, Obj: obj, }, Assign: pos, @@ -454,12 +454,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) { } obj := &ast.Object{ Kind: ast.Con, - Name: "C." + name, + Name: "_Cgo_" + name, } valueSpec := &ast.ValueSpec{ Names: []*ast.Ident{{ NamePos: pos, - Name: "C." + name, + Name: "_Cgo_" + name, Obj: obj, }}, Values: []ast.Expr{expr}, @@ -745,27 +745,27 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr { var typeName string switch typ.kind { case C.CXType_Char_S, C.CXType_Char_U: - typeName = "C.char" + typeName = "_Cgo_char" case C.CXType_SChar: - typeName = "C.schar" + typeName = "_Cgo_schar" case C.CXType_UChar: - typeName = "C.uchar" + typeName = "_Cgo_uchar" case C.CXType_Short: - typeName = "C.short" + typeName = "_Cgo_short" case C.CXType_UShort: - typeName = "C.ushort" + typeName = "_Cgo_ushort" case C.CXType_Int: - typeName = "C.int" + typeName = "_Cgo_int" case C.CXType_UInt: - typeName = "C.uint" + typeName = "_Cgo_uint" case C.CXType_Long: - typeName = "C.long" + typeName = "_Cgo_long" case C.CXType_ULong: - typeName = "C.ulong" + typeName = "_Cgo_ulong" case C.CXType_LongLong: - typeName = "C.longlong" + typeName = "_Cgo_longlong" case C.CXType_ULongLong: - typeName = "C.ulonglong" + typeName = "_Cgo_ulonglong" case C.CXType_Bool: typeName = "bool" case C.CXType_Float, C.CXType_Double, C.CXType_LongDouble: @@ -896,7 +896,7 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr { typeSpelling := getString(C.clang_getTypeSpelling(typ)) typeKindSpelling := getString(C.clang_getTypeKindSpelling(typ.kind)) f.addError(pos, fmt.Sprintf("unknown C type: %v (libclang type kind %s)", typeSpelling, typeKindSpelling)) - typeName = "C." + typeName = "_Cgo_" } return &ast.Ident{ NamePos: pos, @@ -913,7 +913,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp var goName string typeSize := C.clang_Type_getSizeOf(underlyingType) switch name { - case "C.char": + case "_Cgo_char": if typeSize != 1 { // This happens for some very special purpose architectures // (DSPs etc.) that are not currently targeted. @@ -926,7 +926,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp case C.CXType_Char_U: goName = "uint8" } - case "C.schar", "C.short", "C.int", "C.long", "C.longlong": + case "_Cgo_schar", "_Cgo_short", "_Cgo_int", "_Cgo_long", "_Cgo_longlong": switch typeSize { case 1: goName = "int8" @@ -937,7 +937,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp case 8: goName = "int64" } - case "C.uchar", "C.ushort", "C.uint", "C.ulong", "C.ulonglong": + case "_Cgo_uchar", "_Cgo_ushort", "_Cgo_uint", "_Cgo_ulong", "_Cgo_ulonglong": switch typeSize { case 1: goName = "uint8" diff --git a/cgo/testdata/basic.out.go b/cgo/testdata/basic.out.go index 7348ee3791..191cfba38f 100644 --- a/cgo/testdata/basic.out.go +++ b/cgo/testdata/basic.out.go @@ -5,50 +5,50 @@ import "unsafe" var _ unsafe.Pointer -//go:linkname C.CString runtime.cgo_CString -func C.CString(string) *C.char +//go:linkname _Cgo_CString runtime.cgo_CString +func _Cgo_CString(string) *_Cgo_char -//go:linkname C.GoString runtime.cgo_GoString -func C.GoString(*C.char) string +//go:linkname _Cgo_GoString runtime.cgo_GoString +func _Cgo_GoString(*_Cgo_char) string -//go:linkname C.__GoStringN runtime.cgo_GoStringN -func C.__GoStringN(*C.char, uintptr) string +//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN +func _Cgo___GoStringN(*_Cgo_char, uintptr) string -func C.GoStringN(cstr *C.char, length C.int) string { - return C.__GoStringN(cstr, uintptr(length)) +func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string { + return _Cgo___GoStringN(cstr, uintptr(length)) } -//go:linkname C.__GoBytes runtime.cgo_GoBytes -func C.__GoBytes(unsafe.Pointer, uintptr) []byte +//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes +func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte -func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { - return C.__GoBytes(ptr, uintptr(length)) +func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte { + return _Cgo___GoBytes(ptr, uintptr(length)) } -//go:linkname C.__CBytes runtime.cgo_CBytes -func C.__CBytes([]byte) unsafe.Pointer +//go:linkname _Cgo___CBytes runtime.cgo_CBytes +func _Cgo___CBytes([]byte) unsafe.Pointer -func C.CBytes(b []byte) unsafe.Pointer { - return C.__CBytes(b) +func _Cgo_CBytes(b []byte) unsafe.Pointer { + return _Cgo___CBytes(b) } -//go:linkname C.__get_errno_num runtime.cgo_errno -func C.__get_errno_num() uintptr +//go:linkname _Cgo___get_errno_num runtime.cgo_errno +func _Cgo___get_errno_num() uintptr -func C.__get_errno() error { - return syscall.Errno(C.__get_errno_num()) +func _Cgo___get_errno() error { + return syscall.Errno(_Cgo___get_errno_num()) } type ( - C.char uint8 - C.schar int8 - C.uchar uint8 - C.short int16 - C.ushort uint16 - C.int int32 - C.uint uint32 - C.long int32 - C.ulong uint32 - C.longlong int64 - C.ulonglong uint64 + _Cgo_char uint8 + _Cgo_schar int8 + _Cgo_uchar uint8 + _Cgo_short int16 + _Cgo_ushort uint16 + _Cgo_int int32 + _Cgo_uint uint32 + _Cgo_long int32 + _Cgo_ulong uint32 + _Cgo_longlong int64 + _Cgo_ulonglong uint64 ) diff --git a/cgo/testdata/const.out.go b/cgo/testdata/const.out.go index 21705afc4f..0329ba5985 100644 --- a/cgo/testdata/const.out.go +++ b/cgo/testdata/const.out.go @@ -5,58 +5,58 @@ import "unsafe" var _ unsafe.Pointer -//go:linkname C.CString runtime.cgo_CString -func C.CString(string) *C.char +//go:linkname _Cgo_CString runtime.cgo_CString +func _Cgo_CString(string) *_Cgo_char -//go:linkname C.GoString runtime.cgo_GoString -func C.GoString(*C.char) string +//go:linkname _Cgo_GoString runtime.cgo_GoString +func _Cgo_GoString(*_Cgo_char) string -//go:linkname C.__GoStringN runtime.cgo_GoStringN -func C.__GoStringN(*C.char, uintptr) string +//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN +func _Cgo___GoStringN(*_Cgo_char, uintptr) string -func C.GoStringN(cstr *C.char, length C.int) string { - return C.__GoStringN(cstr, uintptr(length)) +func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string { + return _Cgo___GoStringN(cstr, uintptr(length)) } -//go:linkname C.__GoBytes runtime.cgo_GoBytes -func C.__GoBytes(unsafe.Pointer, uintptr) []byte +//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes +func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte -func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { - return C.__GoBytes(ptr, uintptr(length)) +func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte { + return _Cgo___GoBytes(ptr, uintptr(length)) } -//go:linkname C.__CBytes runtime.cgo_CBytes -func C.__CBytes([]byte) unsafe.Pointer +//go:linkname _Cgo___CBytes runtime.cgo_CBytes +func _Cgo___CBytes([]byte) unsafe.Pointer -func C.CBytes(b []byte) unsafe.Pointer { - return C.__CBytes(b) +func _Cgo_CBytes(b []byte) unsafe.Pointer { + return _Cgo___CBytes(b) } -//go:linkname C.__get_errno_num runtime.cgo_errno -func C.__get_errno_num() uintptr +//go:linkname _Cgo___get_errno_num runtime.cgo_errno +func _Cgo___get_errno_num() uintptr -func C.__get_errno() error { - return syscall.Errno(C.__get_errno_num()) +func _Cgo___get_errno() error { + return syscall.Errno(_Cgo___get_errno_num()) } type ( - C.char uint8 - C.schar int8 - C.uchar uint8 - C.short int16 - C.ushort uint16 - C.int int32 - C.uint uint32 - C.long int32 - C.ulong uint32 - C.longlong int64 - C.ulonglong uint64 + _Cgo_char uint8 + _Cgo_schar int8 + _Cgo_uchar uint8 + _Cgo_short int16 + _Cgo_ushort uint16 + _Cgo_int int32 + _Cgo_uint uint32 + _Cgo_long int32 + _Cgo_ulong uint32 + _Cgo_longlong int64 + _Cgo_ulonglong uint64 ) -const C.foo = 3 -const C.bar = C.foo -const C.unreferenced = 4 -const C.referenced = C.unreferenced -const C.fnlike_val = 5 -const C.square_val = (20 * 20) -const C.add_val = (3 + 5) +const _Cgo_foo = 3 +const _Cgo_bar = _Cgo_foo +const _Cgo_unreferenced = 4 +const _Cgo_referenced = _Cgo_unreferenced +const _Cgo_fnlike_val = 5 +const _Cgo_square_val = (20 * 20) +const _Cgo_add_val = (3 + 5) diff --git a/cgo/testdata/errors.out.go b/cgo/testdata/errors.out.go index e0f7d1f541..0ae794087f 100644 --- a/cgo/testdata/errors.out.go +++ b/cgo/testdata/errors.out.go @@ -14,16 +14,16 @@ // testdata/errors.go:3:1: function "unusedFunction" in #cgo noescape line is not used // Type checking errors after CGo processing: -// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as C.char value in variable declaration (overflows) +// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as _Cgo_char value in variable declaration (overflows) // testdata/errors.go:105: unknown field z in struct literal -// testdata/errors.go:108: undefined: C.SOME_CONST_1 -// testdata/errors.go:110: cannot use C.SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows) -// testdata/errors.go:112: undefined: C.SOME_CONST_4 -// testdata/errors.go:114: undefined: C.SOME_CONST_b -// testdata/errors.go:116: undefined: C.SOME_CONST_startspace -// testdata/errors.go:119: undefined: C.SOME_PARAM_CONST_invalid -// testdata/errors.go:122: undefined: C.add_toomuch -// testdata/errors.go:123: undefined: C.add_toolittle +// testdata/errors.go:108: undefined: _Cgo_SOME_CONST_1 +// testdata/errors.go:110: cannot use _Cgo_SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows) +// testdata/errors.go:112: undefined: _Cgo_SOME_CONST_4 +// testdata/errors.go:114: undefined: _Cgo_SOME_CONST_b +// testdata/errors.go:116: undefined: _Cgo_SOME_CONST_startspace +// testdata/errors.go:119: undefined: _Cgo_SOME_PARAM_CONST_invalid +// testdata/errors.go:122: undefined: _Cgo_add_toomuch +// testdata/errors.go:123: undefined: _Cgo_add_toolittle package main @@ -32,58 +32,58 @@ import "unsafe" var _ unsafe.Pointer -//go:linkname C.CString runtime.cgo_CString -func C.CString(string) *C.char +//go:linkname _Cgo_CString runtime.cgo_CString +func _Cgo_CString(string) *_Cgo_char -//go:linkname C.GoString runtime.cgo_GoString -func C.GoString(*C.char) string +//go:linkname _Cgo_GoString runtime.cgo_GoString +func _Cgo_GoString(*_Cgo_char) string -//go:linkname C.__GoStringN runtime.cgo_GoStringN -func C.__GoStringN(*C.char, uintptr) string +//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN +func _Cgo___GoStringN(*_Cgo_char, uintptr) string -func C.GoStringN(cstr *C.char, length C.int) string { - return C.__GoStringN(cstr, uintptr(length)) +func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string { + return _Cgo___GoStringN(cstr, uintptr(length)) } -//go:linkname C.__GoBytes runtime.cgo_GoBytes -func C.__GoBytes(unsafe.Pointer, uintptr) []byte +//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes +func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte -func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { - return C.__GoBytes(ptr, uintptr(length)) +func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte { + return _Cgo___GoBytes(ptr, uintptr(length)) } -//go:linkname C.__CBytes runtime.cgo_CBytes -func C.__CBytes([]byte) unsafe.Pointer +//go:linkname _Cgo___CBytes runtime.cgo_CBytes +func _Cgo___CBytes([]byte) unsafe.Pointer -func C.CBytes(b []byte) unsafe.Pointer { - return C.__CBytes(b) +func _Cgo_CBytes(b []byte) unsafe.Pointer { + return _Cgo___CBytes(b) } -//go:linkname C.__get_errno_num runtime.cgo_errno -func C.__get_errno_num() uintptr +//go:linkname _Cgo___get_errno_num runtime.cgo_errno +func _Cgo___get_errno_num() uintptr -func C.__get_errno() error { - return syscall.Errno(C.__get_errno_num()) +func _Cgo___get_errno() error { + return syscall.Errno(_Cgo___get_errno_num()) } type ( - C.char uint8 - C.schar int8 - C.uchar uint8 - C.short int16 - C.ushort uint16 - C.int int32 - C.uint uint32 - C.long int32 - C.ulong uint32 - C.longlong int64 - C.ulonglong uint64 + _Cgo_char uint8 + _Cgo_schar int8 + _Cgo_uchar uint8 + _Cgo_short int16 + _Cgo_ushort uint16 + _Cgo_int int32 + _Cgo_uint uint32 + _Cgo_long int32 + _Cgo_ulong uint32 + _Cgo_longlong int64 + _Cgo_ulonglong uint64 ) -type C.struct_point_t struct { - x C.int - y C.int +type _Cgo_struct_point_t struct { + x _Cgo_int + y _Cgo_int } -type C.point_t = C.struct_point_t +type _Cgo_point_t = _Cgo_struct_point_t -const C.SOME_CONST_3 = 1234 -const C.SOME_PARAM_CONST_valid = 3 + 4 +const _Cgo_SOME_CONST_3 = 1234 +const _Cgo_SOME_PARAM_CONST_valid = 3 + 4 diff --git a/cgo/testdata/flags.out.go b/cgo/testdata/flags.out.go index 8662412296..ac5cf546db 100644 --- a/cgo/testdata/flags.out.go +++ b/cgo/testdata/flags.out.go @@ -10,53 +10,53 @@ import "unsafe" var _ unsafe.Pointer -//go:linkname C.CString runtime.cgo_CString -func C.CString(string) *C.char +//go:linkname _Cgo_CString runtime.cgo_CString +func _Cgo_CString(string) *_Cgo_char -//go:linkname C.GoString runtime.cgo_GoString -func C.GoString(*C.char) string +//go:linkname _Cgo_GoString runtime.cgo_GoString +func _Cgo_GoString(*_Cgo_char) string -//go:linkname C.__GoStringN runtime.cgo_GoStringN -func C.__GoStringN(*C.char, uintptr) string +//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN +func _Cgo___GoStringN(*_Cgo_char, uintptr) string -func C.GoStringN(cstr *C.char, length C.int) string { - return C.__GoStringN(cstr, uintptr(length)) +func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string { + return _Cgo___GoStringN(cstr, uintptr(length)) } -//go:linkname C.__GoBytes runtime.cgo_GoBytes -func C.__GoBytes(unsafe.Pointer, uintptr) []byte +//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes +func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte -func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { - return C.__GoBytes(ptr, uintptr(length)) +func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte { + return _Cgo___GoBytes(ptr, uintptr(length)) } -//go:linkname C.__CBytes runtime.cgo_CBytes -func C.__CBytes([]byte) unsafe.Pointer +//go:linkname _Cgo___CBytes runtime.cgo_CBytes +func _Cgo___CBytes([]byte) unsafe.Pointer -func C.CBytes(b []byte) unsafe.Pointer { - return C.__CBytes(b) +func _Cgo_CBytes(b []byte) unsafe.Pointer { + return _Cgo___CBytes(b) } -//go:linkname C.__get_errno_num runtime.cgo_errno -func C.__get_errno_num() uintptr +//go:linkname _Cgo___get_errno_num runtime.cgo_errno +func _Cgo___get_errno_num() uintptr -func C.__get_errno() error { - return syscall.Errno(C.__get_errno_num()) +func _Cgo___get_errno() error { + return syscall.Errno(_Cgo___get_errno_num()) } type ( - C.char uint8 - C.schar int8 - C.uchar uint8 - C.short int16 - C.ushort uint16 - C.int int32 - C.uint uint32 - C.long int32 - C.ulong uint32 - C.longlong int64 - C.ulonglong uint64 + _Cgo_char uint8 + _Cgo_schar int8 + _Cgo_uchar uint8 + _Cgo_short int16 + _Cgo_ushort uint16 + _Cgo_int int32 + _Cgo_uint uint32 + _Cgo_long int32 + _Cgo_ulong uint32 + _Cgo_longlong int64 + _Cgo_ulonglong uint64 ) -const C.BAR = 3 -const C.FOO_H = 1 +const _Cgo_BAR = 3 +const _Cgo_FOO_H = 1 diff --git a/cgo/testdata/symbols.out.go b/cgo/testdata/symbols.out.go index 2ca80c1e65..8a603cfd7e 100644 --- a/cgo/testdata/symbols.out.go +++ b/cgo/testdata/symbols.out.go @@ -5,80 +5,80 @@ import "unsafe" var _ unsafe.Pointer -//go:linkname C.CString runtime.cgo_CString -func C.CString(string) *C.char +//go:linkname _Cgo_CString runtime.cgo_CString +func _Cgo_CString(string) *_Cgo_char -//go:linkname C.GoString runtime.cgo_GoString -func C.GoString(*C.char) string +//go:linkname _Cgo_GoString runtime.cgo_GoString +func _Cgo_GoString(*_Cgo_char) string -//go:linkname C.__GoStringN runtime.cgo_GoStringN -func C.__GoStringN(*C.char, uintptr) string +//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN +func _Cgo___GoStringN(*_Cgo_char, uintptr) string -func C.GoStringN(cstr *C.char, length C.int) string { - return C.__GoStringN(cstr, uintptr(length)) +func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string { + return _Cgo___GoStringN(cstr, uintptr(length)) } -//go:linkname C.__GoBytes runtime.cgo_GoBytes -func C.__GoBytes(unsafe.Pointer, uintptr) []byte +//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes +func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte -func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { - return C.__GoBytes(ptr, uintptr(length)) +func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte { + return _Cgo___GoBytes(ptr, uintptr(length)) } -//go:linkname C.__CBytes runtime.cgo_CBytes -func C.__CBytes([]byte) unsafe.Pointer +//go:linkname _Cgo___CBytes runtime.cgo_CBytes +func _Cgo___CBytes([]byte) unsafe.Pointer -func C.CBytes(b []byte) unsafe.Pointer { - return C.__CBytes(b) +func _Cgo_CBytes(b []byte) unsafe.Pointer { + return _Cgo___CBytes(b) } -//go:linkname C.__get_errno_num runtime.cgo_errno -func C.__get_errno_num() uintptr +//go:linkname _Cgo___get_errno_num runtime.cgo_errno +func _Cgo___get_errno_num() uintptr -func C.__get_errno() error { - return syscall.Errno(C.__get_errno_num()) +func _Cgo___get_errno() error { + return syscall.Errno(_Cgo___get_errno_num()) } type ( - C.char uint8 - C.schar int8 - C.uchar uint8 - C.short int16 - C.ushort uint16 - C.int int32 - C.uint uint32 - C.long int32 - C.ulong uint32 - C.longlong int64 - C.ulonglong uint64 + _Cgo_char uint8 + _Cgo_schar int8 + _Cgo_uchar uint8 + _Cgo_short int16 + _Cgo_ushort uint16 + _Cgo_int int32 + _Cgo_uint uint32 + _Cgo_long int32 + _Cgo_ulong uint32 + _Cgo_longlong int64 + _Cgo_ulonglong uint64 ) //export foo -func C.foo(a C.int, b C.int) C.int +func _Cgo_foo(a _Cgo_int, b _Cgo_int) _Cgo_int -var C.foo$funcaddr unsafe.Pointer +var _Cgo_foo$funcaddr unsafe.Pointer //export variadic0 //go:variadic -func C.variadic0() +func _Cgo_variadic0() -var C.variadic0$funcaddr unsafe.Pointer +var _Cgo_variadic0$funcaddr unsafe.Pointer //export variadic2 //go:variadic -func C.variadic2(x C.int, y C.int) +func _Cgo_variadic2(x _Cgo_int, y _Cgo_int) -var C.variadic2$funcaddr unsafe.Pointer +var _Cgo_variadic2$funcaddr unsafe.Pointer //export _Cgo_static_173c95a79b6df1980521_staticfunc -func C.staticfunc!symbols.go(x C.int) +func _Cgo_staticfunc!symbols.go(x _Cgo_int) -var C.staticfunc!symbols.go$funcaddr unsafe.Pointer +var _Cgo_staticfunc!symbols.go$funcaddr unsafe.Pointer //export notEscapingFunction //go:noescape -func C.notEscapingFunction(a *C.int) +func _Cgo_notEscapingFunction(a *_Cgo_int) -var C.notEscapingFunction$funcaddr unsafe.Pointer +var _Cgo_notEscapingFunction$funcaddr unsafe.Pointer //go:extern someValue -var C.someValue C.int +var _Cgo_someValue _Cgo_int diff --git a/cgo/testdata/types.out.go b/cgo/testdata/types.out.go index b3fe414b07..3eaa53f1fb 100644 --- a/cgo/testdata/types.out.go +++ b/cgo/testdata/types.out.go @@ -5,158 +5,162 @@ import "unsafe" var _ unsafe.Pointer -//go:linkname C.CString runtime.cgo_CString -func C.CString(string) *C.char +//go:linkname _Cgo_CString runtime.cgo_CString +func _Cgo_CString(string) *_Cgo_char -//go:linkname C.GoString runtime.cgo_GoString -func C.GoString(*C.char) string +//go:linkname _Cgo_GoString runtime.cgo_GoString +func _Cgo_GoString(*_Cgo_char) string -//go:linkname C.__GoStringN runtime.cgo_GoStringN -func C.__GoStringN(*C.char, uintptr) string +//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN +func _Cgo___GoStringN(*_Cgo_char, uintptr) string -func C.GoStringN(cstr *C.char, length C.int) string { - return C.__GoStringN(cstr, uintptr(length)) +func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string { + return _Cgo___GoStringN(cstr, uintptr(length)) } -//go:linkname C.__GoBytes runtime.cgo_GoBytes -func C.__GoBytes(unsafe.Pointer, uintptr) []byte +//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes +func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte -func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { - return C.__GoBytes(ptr, uintptr(length)) +func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte { + return _Cgo___GoBytes(ptr, uintptr(length)) } -//go:linkname C.__CBytes runtime.cgo_CBytes -func C.__CBytes([]byte) unsafe.Pointer +//go:linkname _Cgo___CBytes runtime.cgo_CBytes +func _Cgo___CBytes([]byte) unsafe.Pointer -func C.CBytes(b []byte) unsafe.Pointer { - return C.__CBytes(b) +func _Cgo_CBytes(b []byte) unsafe.Pointer { + return _Cgo___CBytes(b) } -//go:linkname C.__get_errno_num runtime.cgo_errno -func C.__get_errno_num() uintptr +//go:linkname _Cgo___get_errno_num runtime.cgo_errno +func _Cgo___get_errno_num() uintptr -func C.__get_errno() error { - return syscall.Errno(C.__get_errno_num()) +func _Cgo___get_errno() error { + return syscall.Errno(_Cgo___get_errno_num()) } type ( - C.char uint8 - C.schar int8 - C.uchar uint8 - C.short int16 - C.ushort uint16 - C.int int32 - C.uint uint32 - C.long int32 - C.ulong uint32 - C.longlong int64 - C.ulonglong uint64 + _Cgo_char uint8 + _Cgo_schar int8 + _Cgo_uchar uint8 + _Cgo_short int16 + _Cgo_ushort uint16 + _Cgo_int int32 + _Cgo_uint uint32 + _Cgo_long int32 + _Cgo_ulong uint32 + _Cgo_longlong int64 + _Cgo_ulonglong uint64 ) -type C.myint = C.int -type C.struct_point2d_t struct { - x C.int - y C.int -} -type C.point2d_t = C.struct_point2d_t -type C.struct_point3d struct { - x C.int - y C.int - z C.int -} -type C.point3d_t = C.struct_point3d -type C.struct_type1 struct { - _type C.int - __type C.int - ___type C.int -} -type C.struct_type2 struct{ _type C.int } -type C.union_union1_t struct{ i C.int } -type C.union1_t = C.union_union1_t -type C.union_union3_t struct{ $union uint64 } - -func (union *C.union_union3_t) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) } -func (union *C.union_union3_t) unionfield_d() *float64 { +type _Cgo_myint = _Cgo_int +type _Cgo_struct_point2d_t struct { + x _Cgo_int + y _Cgo_int +} +type _Cgo_point2d_t = _Cgo_struct_point2d_t +type _Cgo_struct_point3d struct { + x _Cgo_int + y _Cgo_int + z _Cgo_int +} +type _Cgo_point3d_t = _Cgo_struct_point3d +type _Cgo_struct_type1 struct { + _type _Cgo_int + __type _Cgo_int + ___type _Cgo_int +} +type _Cgo_struct_type2 struct{ _type _Cgo_int } +type _Cgo_union_union1_t struct{ i _Cgo_int } +type _Cgo_union1_t = _Cgo_union_union1_t +type _Cgo_union_union3_t struct{ $union uint64 } + +func (union *_Cgo_union_union3_t) unionfield_i() *_Cgo_int { + return (*_Cgo_int)(unsafe.Pointer(&union.$union)) +} +func (union *_Cgo_union_union3_t) unionfield_d() *float64 { return (*float64)(unsafe.Pointer(&union.$union)) } -func (union *C.union_union3_t) unionfield_s() *C.short { - return (*C.short)(unsafe.Pointer(&union.$union)) +func (union *_Cgo_union_union3_t) unionfield_s() *_Cgo_short { + return (*_Cgo_short)(unsafe.Pointer(&union.$union)) } -type C.union3_t = C.union_union3_t -type C.union_union2d struct{ $union [2]uint64 } +type _Cgo_union3_t = _Cgo_union_union3_t +type _Cgo_union_union2d struct{ $union [2]uint64 } -func (union *C.union_union2d) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) } -func (union *C.union_union2d) unionfield_d() *[2]float64 { +func (union *_Cgo_union_union2d) unionfield_i() *_Cgo_int { + return (*_Cgo_int)(unsafe.Pointer(&union.$union)) +} +func (union *_Cgo_union_union2d) unionfield_d() *[2]float64 { return (*[2]float64)(unsafe.Pointer(&union.$union)) } -type C.union2d_t = C.union_union2d -type C.union_unionarray_t struct{ arr [10]C.uchar } -type C.unionarray_t = C.union_unionarray_t -type C._Ctype_union___0 struct{ $union [3]uint32 } +type _Cgo_union2d_t = _Cgo_union_union2d +type _Cgo_union_unionarray_t struct{ arr [10]_Cgo_uchar } +type _Cgo_unionarray_t = _Cgo_union_unionarray_t +type _Cgo__Ctype_union___0 struct{ $union [3]uint32 } -func (union *C._Ctype_union___0) unionfield_area() *C.point2d_t { - return (*C.point2d_t)(unsafe.Pointer(&union.$union)) +func (union *_Cgo__Ctype_union___0) unionfield_area() *_Cgo_point2d_t { + return (*_Cgo_point2d_t)(unsafe.Pointer(&union.$union)) } -func (union *C._Ctype_union___0) unionfield_solid() *C.point3d_t { - return (*C.point3d_t)(unsafe.Pointer(&union.$union)) +func (union *_Cgo__Ctype_union___0) unionfield_solid() *_Cgo_point3d_t { + return (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union)) } -type C.struct_struct_nested_t struct { - begin C.point2d_t - end C.point2d_t - tag C.int +type _Cgo_struct_struct_nested_t struct { + begin _Cgo_point2d_t + end _Cgo_point2d_t + tag _Cgo_int - coord C._Ctype_union___0 + coord _Cgo__Ctype_union___0 } -type C.struct_nested_t = C.struct_struct_nested_t -type C.union_union_nested_t struct{ $union [2]uint64 } +type _Cgo_struct_nested_t = _Cgo_struct_struct_nested_t +type _Cgo_union_union_nested_t struct{ $union [2]uint64 } -func (union *C.union_union_nested_t) unionfield_point() *C.point3d_t { - return (*C.point3d_t)(unsafe.Pointer(&union.$union)) +func (union *_Cgo_union_union_nested_t) unionfield_point() *_Cgo_point3d_t { + return (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union)) } -func (union *C.union_union_nested_t) unionfield_array() *C.unionarray_t { - return (*C.unionarray_t)(unsafe.Pointer(&union.$union)) +func (union *_Cgo_union_union_nested_t) unionfield_array() *_Cgo_unionarray_t { + return (*_Cgo_unionarray_t)(unsafe.Pointer(&union.$union)) } -func (union *C.union_union_nested_t) unionfield_thing() *C.union3_t { - return (*C.union3_t)(unsafe.Pointer(&union.$union)) +func (union *_Cgo_union_union_nested_t) unionfield_thing() *_Cgo_union3_t { + return (*_Cgo_union3_t)(unsafe.Pointer(&union.$union)) } -type C.union_nested_t = C.union_union_nested_t -type C.enum_option = C.int -type C.option_t = C.enum_option -type C.enum_option2_t = C.uint -type C.option2_t = C.enum_option2_t -type C.struct_types_t struct { +type _Cgo_union_nested_t = _Cgo_union_union_nested_t +type _Cgo_enum_option = _Cgo_int +type _Cgo_option_t = _Cgo_enum_option +type _Cgo_enum_option2_t = _Cgo_uint +type _Cgo_option2_t = _Cgo_enum_option2_t +type _Cgo_struct_types_t struct { f float32 d float64 - ptr *C.int + ptr *_Cgo_int } -type C.types_t = C.struct_types_t -type C.myIntArray = [10]C.int -type C.struct_bitfield_t struct { - start C.uchar - __bitfield_1 C.uchar +type _Cgo_types_t = _Cgo_struct_types_t +type _Cgo_myIntArray = [10]_Cgo_int +type _Cgo_struct_bitfield_t struct { + start _Cgo_uchar + __bitfield_1 _Cgo_uchar - d C.uchar - e C.uchar + d _Cgo_uchar + e _Cgo_uchar } -func (s *C.struct_bitfield_t) bitfield_a() C.uchar { return s.__bitfield_1 & 0x1f } -func (s *C.struct_bitfield_t) set_bitfield_a(value C.uchar) { +func (s *_Cgo_struct_bitfield_t) bitfield_a() _Cgo_uchar { return s.__bitfield_1 & 0x1f } +func (s *_Cgo_struct_bitfield_t) set_bitfield_a(value _Cgo_uchar) { s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0 } -func (s *C.struct_bitfield_t) bitfield_b() C.uchar { +func (s *_Cgo_struct_bitfield_t) bitfield_b() _Cgo_uchar { return s.__bitfield_1 >> 5 & 0x1 } -func (s *C.struct_bitfield_t) set_bitfield_b(value C.uchar) { +func (s *_Cgo_struct_bitfield_t) set_bitfield_b(value _Cgo_uchar) { s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5 } -func (s *C.struct_bitfield_t) bitfield_c() C.uchar { +func (s *_Cgo_struct_bitfield_t) bitfield_c() _Cgo_uchar { return s.__bitfield_1 >> 6 } -func (s *C.struct_bitfield_t) set_bitfield_c(value C.uchar, +func (s *_Cgo_struct_bitfield_t) set_bitfield_c(value _Cgo_uchar, ) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 } -type C.bitfield_t = C.struct_bitfield_t +type _Cgo_bitfield_t = _Cgo_struct_bitfield_t diff --git a/compiler/symbol.go b/compiler/symbol.go index 5ecf68e54a..1de3c6f39d 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -432,9 +432,8 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) { // pass for C variadic functions. This includes both explicit // (with ...) and implicit (no parameters in signature) // functions. - if strings.HasPrefix(f.Name(), "C.") { - // This prefix cannot naturally be created, it must have - // been created as a result of CGo preprocessing. + if strings.HasPrefix(f.Name(), "_Cgo_") { + // This prefix was created as a result of CGo preprocessing. info.variadic = true } } From 9dc5a7d6d77380eac6ebbe67ae76153b28f691ca Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 16 Feb 2025 15:11:39 +0100 Subject: [PATCH 02/10] machine: remove bytes package dependency in flash code This also moves flash padding code to a single place, since it was copied 5 times. This change is necessary in Go 1.24 to avoid an import cycle. --- src/machine/flash.go | 11 +++++++++++ src/machine/machine_atsamd21.go | 14 +------------- src/machine/machine_atsamd51.go | 14 +------------- src/machine/machine_nrf.go | 14 +------------- src/machine/machine_rp2040_flash.go | 12 ------------ src/machine/machine_rp2040_rom.go | 2 +- src/machine/machine_stm32_flash.go | 15 ++------------- 7 files changed, 17 insertions(+), 65 deletions(-) diff --git a/src/machine/flash.go b/src/machine/flash.go index 716fc4a53b..da832afdb8 100644 --- a/src/machine/flash.go +++ b/src/machine/flash.go @@ -64,3 +64,14 @@ type BlockDevice interface { // EraseBlockSize to map addresses to blocks. EraseBlocks(start, len int64) error } + +// pad data if needed so it is long enough for correct byte alignment on writes. +func flashPad(p []byte, writeBlockSize int) []byte { + overflow := len(p) % writeBlockSize + if overflow != 0 { + for i := 0; i < writeBlockSize-overflow; i++ { + p = append(p, 0xff) + } + } + return p +} diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go index 3d0abc0fa8..0a5c320ca0 100644 --- a/src/machine/machine_atsamd21.go +++ b/src/machine/machine_atsamd21.go @@ -7,7 +7,6 @@ package machine import ( - "bytes" "device/arm" "device/sam" "errors" @@ -1917,7 +1916,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) { f.ensureInitComplete() address := FlashDataStart() + uintptr(off) - padded := f.pad(p) + padded := flashPad(p, int(f.WriteBlockSize())) waitWhileFlashBusy() @@ -1992,17 +1991,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error { return nil } -// pad data if needed so it is long enough for correct byte alignment on writes. -func (f flashBlockDevice) pad(p []byte) []byte { - overflow := int64(len(p)) % f.WriteBlockSize() - if overflow == 0 { - return p - } - - padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow)) - return append(p, padding...) -} - func (f flashBlockDevice) ensureInitComplete() { if f.initComplete { return diff --git a/src/machine/machine_atsamd51.go b/src/machine/machine_atsamd51.go index bcaaec7212..5cd1d314a2 100644 --- a/src/machine/machine_atsamd51.go +++ b/src/machine/machine_atsamd51.go @@ -7,7 +7,6 @@ package machine import ( - "bytes" "device/arm" "device/sam" "errors" @@ -2174,7 +2173,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) { } address := FlashDataStart() + uintptr(off) - padded := f.pad(p) + padded := flashPad(p, int(f.WriteBlockSize())) settings := disableFlashCache() defer restoreFlashCache(settings) @@ -2263,17 +2262,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error { return nil } -// pad data if needed so it is long enough for correct byte alignment on writes. -func (f flashBlockDevice) pad(p []byte) []byte { - overflow := int64(len(p)) % f.WriteBlockSize() - if overflow == 0 { - return p - } - - padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow)) - return append(p, padding...) -} - func disableFlashCache() uint16 { settings := sam.NVMCTRL.CTRLA.Get() diff --git a/src/machine/machine_nrf.go b/src/machine/machine_nrf.go index 4da6645352..d6d6349f29 100644 --- a/src/machine/machine_nrf.go +++ b/src/machine/machine_nrf.go @@ -3,7 +3,6 @@ package machine import ( - "bytes" "device/nrf" "internal/binary" "runtime/interrupt" @@ -386,7 +385,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) { } address := FlashDataStart() + uintptr(off) - padded := f.pad(p) + padded := flashPad(p, int(f.WriteBlockSize())) waitWhileFlashBusy() @@ -444,17 +443,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error { return nil } -// pad data if needed so it is long enough for correct byte alignment on writes. -func (f flashBlockDevice) pad(p []byte) []byte { - overflow := int64(len(p)) % f.WriteBlockSize() - if overflow == 0 { - return p - } - - padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow)) - return append(p, padding...) -} - func waitWhileFlashBusy() { for nrf.NVMC.GetREADY() != nrf.NVMC_READY_READY_Ready { } diff --git a/src/machine/machine_rp2040_flash.go b/src/machine/machine_rp2040_flash.go index 8ee881e19a..1317c0926a 100644 --- a/src/machine/machine_rp2040_flash.go +++ b/src/machine/machine_rp2040_flash.go @@ -3,7 +3,6 @@ package machine import ( - "bytes" "unsafe" ) @@ -101,17 +100,6 @@ func (f flashBlockDevice) EraseBlocks(start, length int64) error { return f.eraseBlocks(start, length) } -// pad data if needed so it is long enough for correct byte alignment on writes. -func (f flashBlockDevice) pad(p []byte) []byte { - overflow := int64(len(p)) % f.WriteBlockSize() - if overflow == 0 { - return p - } - - padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow)) - return append(p, padding...) -} - // return the correct address to be used for write func writeAddress(off int64) uintptr { return readAddress(off) - uintptr(memoryStart) diff --git a/src/machine/machine_rp2040_rom.go b/src/machine/machine_rp2040_rom.go index eea461882d..5541e2a9bf 100644 --- a/src/machine/machine_rp2040_rom.go +++ b/src/machine/machine_rp2040_rom.go @@ -230,7 +230,7 @@ func (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) { // e.g. real address 0x10003000 is written to at // 0x00003000 address := writeAddress(off) - padded := f.pad(p) + padded := flashPad(p, int(f.WriteBlockSize())) C.flash_range_write(C.uint32_t(address), (*C.uint8_t)(unsafe.Pointer(&padded[0])), diff --git a/src/machine/machine_stm32_flash.go b/src/machine/machine_stm32_flash.go index 710aa05d00..280dc8987e 100644 --- a/src/machine/machine_stm32_flash.go +++ b/src/machine/machine_stm32_flash.go @@ -5,7 +5,6 @@ package machine import ( "device/stm32" - "bytes" "unsafe" ) @@ -41,7 +40,8 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) { unlockFlash() defer lockFlash() - return writeFlashData(FlashDataStart()+uintptr(off), f.pad(p)) + p = flashPad(p, int(f.WriteBlockSize())) + return writeFlashData(FlashDataStart()+uintptr(off), p) } // Size returns the number of bytes in this block device. @@ -90,17 +90,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error { return nil } -// pad data if needed so it is long enough for correct byte alignment on writes. -func (f flashBlockDevice) pad(p []byte) []byte { - overflow := int64(len(p)) % f.WriteBlockSize() - if overflow == 0 { - return p - } - - padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow)) - return append(p, padding...) -} - const memoryStart = 0x08000000 func unlockFlash() { From 0d13e1e5e87d085bce38cecc3ca801093419b13c Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 16 Feb 2025 15:29:55 +0100 Subject: [PATCH 03/10] machine/usb/descriptor: avoid bytes package We can't use the bytes package in Go 1.24 since it would result in an import cycle. Therefore, use bytealg.Index instead. (I'm not sure this code is correct - just searching for a range of bytes seems brittle. But at least this commit shouldn't change the code). --- src/machine/usb/descriptor/hid.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/usb/descriptor/hid.go b/src/machine/usb/descriptor/hid.go index ea65f1ed97..06b9801530 100644 --- a/src/machine/usb/descriptor/hid.go +++ b/src/machine/usb/descriptor/hid.go @@ -1,9 +1,9 @@ package descriptor import ( - "bytes" "errors" "internal/binary" + "internal/bytealg" ) var configurationCDCHID = [configurationTypeLen]byte{ @@ -87,7 +87,7 @@ func FindClassHIDType(des, class []byte) (ClassHIDType, error) { // search only for ClassHIDType without the ClassLength, // in case it has already been set. - idx := bytes.Index(des, class[:ClassHIDTypeLen-2]) + idx := bytealg.Index(des, class[:ClassHIDTypeLen-2]) if idx == -1 { return ClassHIDType{}, errNoClassHIDFound } From 3ff0cd8171cadf82c8f6543bd93fa14e618e970d Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Tue, 18 Feb 2025 14:19:46 +0100 Subject: [PATCH 04/10] runtime: add FIPS helper functions Not entirely sure what they're for, but the Go runtime also stores this information per goroutine so let's go with that. --- src/internal/task/task.go | 3 +++ src/runtime/panic.go | 5 +++++ src/runtime/scheduler.go | 11 +++++++++++ 3 files changed, 19 insertions(+) diff --git a/src/internal/task/task.go b/src/internal/task/task.go index 546f5ba117..58c02fe846 100644 --- a/src/internal/task/task.go +++ b/src/internal/task/task.go @@ -21,6 +21,9 @@ type Task struct { // state is the underlying running state of the task. state state + // This is needed for some crypto packages. + FipsIndicator uint8 + // DeferFrame stores a pointer to the (stack allocated) defer frame of the // goroutine that is used for the recover builtin. DeferFrame unsafe.Pointer diff --git a/src/runtime/panic.go b/src/runtime/panic.go index ec33a4469c..9ae1f982b9 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -226,3 +226,8 @@ func divideByZeroPanic() { func blockingPanic() { runtimePanicAt(returnAddress(0), "trying to do blocking operation in exported function") } + +//go:linkname fips_fatal crypto/internal/fips140.fatal +func fips_fatal(msg string) { + runtimePanic(msg) +} diff --git a/src/runtime/scheduler.go b/src/runtime/scheduler.go index 727c7f5f2c..40740da310 100644 --- a/src/runtime/scheduler.go +++ b/src/runtime/scheduler.go @@ -31,3 +31,14 @@ func scheduleLogChan(msg string, ch *channel, t *task.Task) { func Goexit() { panicOrGoexit(nil, panicGoexit) } + +//go:linkname fips_getIndicator crypto/internal/fips140.getIndicator +func fips_getIndicator() uint8 { + return task.Current().FipsIndicator +} + +//go:linkname fips_setIndicator crypto/internal/fips140.setIndicator +func fips_setIndicator(indicator uint8) { + // This indicator is stored per goroutine. + task.Current().FipsIndicator = indicator +} From 29927b2f949c387de268c87bd2c07f60ccbb3b19 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Tue, 18 Feb 2025 14:21:44 +0100 Subject: [PATCH 05/10] syscall: add wasip1 RandomGet This function is needed starting with Go 1.24. --- src/syscall/syscall_libc_wasi.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/syscall/syscall_libc_wasi.go b/src/syscall/syscall_libc_wasi.go index bbf81cd059..583e7d8ef4 100644 --- a/src/syscall/syscall_libc_wasi.go +++ b/src/syscall/syscall_libc_wasi.go @@ -438,6 +438,13 @@ type RawSockaddrInet6 struct { // stub } +func RandomGet(b []byte) error { + if len(b) > 0 { + libc_arc4random_buf(unsafe.Pointer(&b[0]), uint(len(b))) + } + return nil +} + // This is a stub, it is not functional. func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) @@ -483,3 +490,8 @@ func libc_fdclosedir(unsafe.Pointer) int32 // //export readdir func libc_readdir(unsafe.Pointer) *Dirent + +// void arc4random_buf(void *buf, size_t buflen); +// +//export arc4random_buf +func libc_arc4random_buf(buf unsafe.Pointer, buflen uint) From 9ac4021812bb718d1d1b8cbfd60bb3005ecf28c4 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 24 Feb 2025 16:25:59 +0100 Subject: [PATCH 06/10] os: implement stub Chdir for non-OS systems --- src/os/file_other.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/os/file_other.go b/src/os/file_other.go index 75c0332817..e0705c78dc 100644 --- a/src/os/file_other.go +++ b/src/os/file_other.go @@ -42,6 +42,12 @@ func NewFile(fd uintptr, name string) *File { return &File{&file{handle: stdioFileHandle(fd), name: name}} } +// Chdir changes the current working directory to the named directory. +// If there is an error, it will be of type *PathError. +func Chdir(dir string) error { + return ErrNotImplemented +} + // Rename renames (moves) oldpath to newpath. // If newpath already exists and is not a directory, Rename replaces it. // OS-specific restrictions may apply when oldpath and newpath are in different directories. From a3ba25943d64b6abfff39ab1b866bfe8c9b41853 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 24 Feb 2025 15:42:29 +0100 Subject: [PATCH 07/10] os: add File.Chdir support We should really be using syscall.Fchdir here, but this is a fix to get Go 1.24 working. --- src/os/file.go | 11 +++++++++++ src/os/file_other.go | 4 ++++ src/os/file_unix.go | 16 ++++++++++++++++ src/os/file_windows.go | 4 ++++ 4 files changed, 35 insertions(+) diff --git a/src/os/file.go b/src/os/file.go index 0e20d1bf10..e7dd214b73 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -318,6 +318,17 @@ func (f *File) Chmod(mode FileMode) (err error) { return } +// Chdir changes the current working directory to the file, which must be a +// directory. If there is an error, it will be of type *PathError. +func (f *File) Chdir() (err error) { + if f.handle == nil { + err = ErrClosed + } else { + err = f.chdir() + } + return +} + // LinkError records an error during a link or symlink or rename system call and // the paths that caused it. type LinkError struct { diff --git a/src/os/file_other.go b/src/os/file_other.go index e0705c78dc..8e7d33e00e 100644 --- a/src/os/file_other.go +++ b/src/os/file_other.go @@ -159,3 +159,7 @@ func (f *File) Truncate(size int64) (err error) { func (f *File) chmod(mode FileMode) error { return ErrUnsupported } + +func (f *File) chdir() error { + return ErrNotImplemented +} diff --git a/src/os/file_unix.go b/src/os/file_unix.go index fd4d464f5b..9dc3a91e09 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -166,6 +166,22 @@ func (f *File) chmod(mode FileMode) error { return nil } +func (f *File) chdir() error { + if f.handle == nil { + return ErrClosed + } + + // TODO: use syscall.Fchdir instead + longName := fixLongPath(f.name) + e := ignoringEINTR(func() error { + return syscall.Chdir(longName) + }) + if e != nil { + return &PathError{Op: "chdir", Path: f.name, Err: e} + } + return nil +} + // ReadAt reads up to len(b) bytes from the File starting at the given absolute offset. // It returns the number of bytes read and any error encountered, possibly io.EOF. // At end of file, Pread returns 0, io.EOF. diff --git a/src/os/file_windows.go b/src/os/file_windows.go index 022381deed..50c5ee7a82 100644 --- a/src/os/file_windows.go +++ b/src/os/file_windows.go @@ -146,3 +146,7 @@ func isWindowsNulName(name string) bool { func (f *File) chmod(mode FileMode) error { return ErrNotImplemented } + +func (f *File) chdir() error { + return ErrNotImplemented +} From e0a8b2c859712bc41325f7dd59dfa924c6628a4d Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 24 Feb 2025 15:43:41 +0100 Subject: [PATCH 08/10] testing: add Chdir This method was added in Go 1.24. --- src/testing/testing.go | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/testing/testing.go b/src/testing/testing.go index 9058892d28..c4449cbb0a 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -17,6 +17,8 @@ import ( "io/fs" "math/rand" "os" + "path/filepath" + "runtime" "strconv" "strings" "time" @@ -390,6 +392,49 @@ func (c *common) Setenv(key, value string) { } } +// Chdir calls os.Chdir(dir) and uses Cleanup to restore the current +// working directory to its original value after the test. On Unix, it +// also sets PWD environment variable for the duration of the test. +// +// Because Chdir affects the whole process, it cannot be used +// in parallel tests or tests with parallel ancestors. +func (c *common) Chdir(dir string) { + // Note: function copied from the Go 1.24.0 source tree. + + oldwd, err := os.Open(".") + if err != nil { + c.Fatal(err) + } + if err := os.Chdir(dir); err != nil { + c.Fatal(err) + } + // On POSIX platforms, PWD represents “an absolute pathname of the + // current working directory.” Since we are changing the working + // directory, we should also set or update PWD to reflect that. + switch runtime.GOOS { + case "windows", "plan9": + // Windows and Plan 9 do not use the PWD variable. + default: + if !filepath.IsAbs(dir) { + dir, err = os.Getwd() + if err != nil { + c.Fatal(err) + } + } + c.Setenv("PWD", dir) + } + c.Cleanup(func() { + err := oldwd.Chdir() + oldwd.Close() + if err != nil { + // It's not safe to continue with tests if we can't + // get back to the original working directory. Since + // we are holding a dirfd, this is highly unlikely. + panic("testing.Chdir: " + err.Error()) + } + }) +} + // runCleanup is called at the end of the test. func (c *common) runCleanup() { for { From cd41d7df00a5cdc7336bff7181f0142f9a02a0bf Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 24 Feb 2025 15:49:20 +0100 Subject: [PATCH 09/10] wasip2: add stubs to get internal/syscall/unix to work This fixes lots of broken tests in stdlib packages in Go 1.24. --- src/syscall/syscall_libc.go | 4 ++++ src/syscall/syscall_libc_wasi.go | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/syscall/syscall_libc.go b/src/syscall/syscall_libc.go index 0ef9784283..86c756383e 100644 --- a/src/syscall/syscall_libc.go +++ b/src/syscall/syscall_libc.go @@ -233,6 +233,10 @@ func (w WaitStatus) Continued() bool { return false } func (w WaitStatus) StopSignal() Signal { return 0 } func (w WaitStatus) TrapCause() int { return 0 } +// Purely here for compatibility. +type Rusage struct { +} + // since rusage is quite a big struct and we stub it out anyway no need to define it here func Wait4(pid int, wstatus *WaitStatus, options int, rusage uintptr) (wpid int, err error) { return 0, ENOSYS // TODO diff --git a/src/syscall/syscall_libc_wasi.go b/src/syscall/syscall_libc_wasi.go index 583e7d8ef4..479377877b 100644 --- a/src/syscall/syscall_libc_wasi.go +++ b/src/syscall/syscall_libc_wasi.go @@ -120,8 +120,11 @@ const ( SYS_FCNTL64 SYS_FSTATAT64 SYS_IOCTL + SYS_MKDIRAT SYS_OPENAT + SYS_READLINKAT SYS_UNLINKAT + SYS_WAITID PATH_MAX = 4096 ) From c0bd14d57b8a1f56ae3c3ad341b850065f8a9e32 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 12 Feb 2025 16:11:08 +0100 Subject: [PATCH 10/10] all: add Go 1.24 support --- .circleci/config.yml | 6 +++--- .github/workflows/build-macos.yml | 4 ++-- .github/workflows/linux.yml | 8 ++++---- .github/workflows/windows.yml | 8 ++++---- Dockerfile | 4 ++-- GNUmakefile | 14 ++++---------- builder/config.go | 4 ++-- builder/sizes_test.go | 2 +- compiler/alias.go | 11 ++++++----- src/internal/abi/type.go | 7 +++++++ src/reflect/value.go | 4 ++++ src/runtime/synctest.go | 15 +++++++++++++++ src/runtime/time.go | 13 +++++++++++++ 13 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 src/internal/abi/type.go create mode 100644 src/runtime/synctest.go diff --git a/.circleci/config.yml b/.circleci/config.yml index e2069e3485..a3a052c28c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -109,9 +109,9 @@ jobs: # "make lint" fails before go 1.21 because internal/tools/go.mod specifies packages that require go 1.21 fmt-check: false resource_class: large - test-llvm19-go123: + test-llvm19-go124: docker: - - image: golang:1.23-bullseye + - image: golang:1.24-bullseye steps: - test-linux: llvm: "19" @@ -124,4 +124,4 @@ workflows: # least the smoke tests still pass. - test-llvm15-go119 # This tests LLVM 19 support when linking against system libraries. - - test-llvm19-go123 + - test-llvm19-go124 diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 07b0d307d0..25b5971783 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -39,7 +39,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Restore LLVM source cache uses: actions/cache/restore@v4 @@ -143,7 +143,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Build TinyGo (LLVM ${{ matrix.version }}) run: go install -tags=llvm${{ matrix.version }} diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index c94b3582e3..cbb0a7c554 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -18,7 +18,7 @@ jobs: # statically linked binary. runs-on: ubuntu-latest container: - image: golang:1.23-alpine + image: golang:1.24-alpine outputs: version: ${{ steps.version.outputs.version }} steps: @@ -146,7 +146,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Install wasmtime uses: bytecodealliance/actions/wasmtime/setup@v1 @@ -189,7 +189,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Install Node.js uses: actions/setup-node@v4 @@ -315,7 +315,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Restore LLVM source cache uses: actions/cache/restore@v4 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e1794ef13b..42365f59b7 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -41,7 +41,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Restore cached LLVM source uses: actions/cache/restore@v4 @@ -156,7 +156,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Download TinyGo build uses: actions/download-artifact@v4 @@ -186,7 +186,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Download TinyGo build uses: actions/download-artifact@v4 @@ -222,7 +222,7 @@ jobs: - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Download TinyGo build uses: actions/download-artifact@v4 diff --git a/Dockerfile b/Dockerfile index 9a9effac2b..520ad7c9b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # tinygo-llvm stage obtains the llvm source for TinyGo -FROM golang:1.23 AS tinygo-llvm +FROM golang:1.24 AS tinygo-llvm RUN apt-get update && \ apt-get install -y apt-utils make cmake clang-15 ninja-build && \ @@ -33,7 +33,7 @@ RUN cd /tinygo/ && \ # tinygo-compiler copies the compiler build over to a base Go container (without # all the build tools etc). -FROM golang:1.23 AS tinygo-compiler +FROM golang:1.24 AS tinygo-compiler # Copy tinygo build. COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo diff --git a/GNUmakefile b/GNUmakefile index 423a2a20e0..28031ffec5 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -309,11 +309,9 @@ TEST_PACKAGES_FAST = \ container/heap \ container/list \ container/ring \ - crypto/des \ crypto/ecdsa \ crypto/elliptic \ crypto/md5 \ - crypto/rc4 \ crypto/sha1 \ crypto/sha256 \ crypto/sha512 \ @@ -355,17 +353,11 @@ TEST_PACKAGES_FAST = \ unique \ $(nil) -# Assume this will go away before Go2, so only check minor version. -ifeq ($(filter $(shell $(GO) env GOVERSION | cut -f 2 -d.), 16 17 18), ) -TEST_PACKAGES_FAST += crypto/internal/nistec/fiat -else -TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat -endif - # archive/zip requires os.ReadAt, which is not yet supported on windows # bytes requires mmap # compress/flate appears to hang on wasi # crypto/aes fails on wasi, needs panic()/recover() +# crypto/des fails on wasi, needs panic()/recover() # crypto/hmac fails on wasi, it exits with a "slice out of range" panic # debug/plan9obj requires os.ReadAt, which is not yet supported on windows # image requires recover(), which is not yet supported on wasi @@ -386,6 +378,7 @@ TEST_PACKAGES_LINUX := \ archive/zip \ compress/flate \ crypto/aes \ + crypto/des \ crypto/hmac \ debug/dwarf \ debug/plan9obj \ @@ -405,10 +398,11 @@ TEST_PACKAGES_LINUX := \ TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX) +# os/user requires t.Skip() support TEST_PACKAGES_WINDOWS := \ compress/flate \ + crypto/des \ crypto/hmac \ - os/user \ strconv \ text/template/parse \ $(nil) diff --git a/builder/config.go b/builder/config.go index d1d0a2713b..b36b9333f3 100644 --- a/builder/config.go +++ b/builder/config.go @@ -26,7 +26,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) { // Version range supported by TinyGo. const minorMin = 19 - const minorMax = 23 + const minorMax = 24 // Check that we support this Go toolchain version. gorootMajor, gorootMinor, err := goenv.GetGorootVersion() @@ -36,7 +36,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) { if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax { // Note: when this gets updated, also update the Go compatibility matrix: // https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md - return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", gorootMajor, gorootMinor) + return nil, fmt.Errorf("requires go version 1.%d through 1.%d, got go%d.%d", minorMin, minorMax, gorootMajor, gorootMinor) } // Check that the Go toolchain version isn't too new, if we haven't been diff --git a/builder/sizes_test.go b/builder/sizes_test.go index 2b2b08fe6f..a96ce9e6f6 100644 --- a/builder/sizes_test.go +++ b/builder/sizes_test.go @@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) { // microcontrollers {"hifive1b", "examples/echo", 4560, 280, 0, 2268}, {"microbit", "examples/serial", 2916, 388, 8, 2272}, - {"wioterminal", "examples/pininterrupt", 7315, 1489, 116, 6912}, + {"wioterminal", "examples/pininterrupt", 7359, 1489, 116, 6912}, // TODO: also check wasm. Right now this is difficult, because // wasm binaries are run through wasm-opt and therefore the diff --git a/compiler/alias.go b/compiler/alias.go index b0191a7a11..9d57a587e7 100644 --- a/compiler/alias.go +++ b/compiler/alias.go @@ -18,11 +18,12 @@ var stdlibAliases = map[string]string{ // crypto packages "crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric", "crypto/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric", - "crypto/md5.block": "crypto/md5.blockGeneric", - "crypto/sha1.block": "crypto/sha1.blockGeneric", - "crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric", - "crypto/sha256.block": "crypto/sha256.blockGeneric", - "crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric", + "crypto/md5.block": "crypto/md5.blockGeneric", + "crypto/sha1.block": "crypto/sha1.blockGeneric", + "crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric", + "crypto/sha256.block": "crypto/sha256.blockGeneric", + "crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric", + "internal/chacha8rand.block": "internal/chacha8rand.block_generic", // AES "crypto/aes.decryptBlockAsm": "crypto/aes.decryptBlock", diff --git a/src/internal/abi/type.go b/src/internal/abi/type.go new file mode 100644 index 0000000000..d1853e0f3d --- /dev/null +++ b/src/internal/abi/type.go @@ -0,0 +1,7 @@ +package abi + +type Type struct { + // Intentionally left empty. TinyGo uses a different way to represent types, + // so this is unimplementable. The type definition here is purely for + // compatibility. +} diff --git a/src/reflect/value.go b/src/reflect/value.go index 69b57fd1cc..7ac71aa184 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -271,6 +271,10 @@ func (v Value) Comparable() bool { } } +func (v Value) Equal(u Value) bool { + panic("unimplemented: reflect.Value.Equal") +} + func (v Value) Addr() Value { if !v.CanAddr() { panic("reflect.Value.Addr of unaddressable value") diff --git a/src/runtime/synctest.go b/src/runtime/synctest.go new file mode 100644 index 0000000000..fa11c991fc --- /dev/null +++ b/src/runtime/synctest.go @@ -0,0 +1,15 @@ +package runtime + +// Dummy implementation of synctest functions (we don't support synctest at the +// moment). + +//go:linkname synctest_acquire internal/synctest.acquire +func synctest_acquire() any { + // Dummy: we don't support synctest. + return nil +} + +//go:linkname synctest_release internal/synctest.release +func synctest_release(sg any) { + // Dummy: we don't support synctest. +} diff --git a/src/runtime/time.go b/src/runtime/time.go index 50bf61cf3c..3935b4486e 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -1,5 +1,18 @@ package runtime +//go:linkname time_runtimeNano time.runtimeNano +func time_runtimeNano() int64 { + // Note: we're ignoring sync groups here (package testing/synctest). + // See: https://github.com/golang/go/issues/67434 + return nanotime() +} + +//go:linkname time_runtimeNow time.runtimeNow +func time_runtimeNow() (sec int64, nsec int32, mono int64) { + // Also ignoring the sync group here, like time_runtimeNano above. + return now() +} + // timerNode is an element in a linked list of timers. type timerNode struct { next *timerNode