Skip to content

Commit ea53ace

Browse files
aykevldeadprogram
authored andcommitted
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 golang/go#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.
1 parent a6cd072 commit ea53ace

File tree

9 files changed

+371
-387
lines changed

9 files changed

+371
-387
lines changed

cgo/cgo.go

+45-64
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,18 @@ type noescapingFunc struct {
9292
// cgoAliases list type aliases between Go and C, for types that are equivalent
9393
// in both languages. See addTypeAliases.
9494
var cgoAliases = map[string]string{
95-
"C.int8_t": "int8",
96-
"C.int16_t": "int16",
97-
"C.int32_t": "int32",
98-
"C.int64_t": "int64",
99-
"C.uint8_t": "uint8",
100-
"C.uint16_t": "uint16",
101-
"C.uint32_t": "uint32",
102-
"C.uint64_t": "uint64",
103-
"C.uintptr_t": "uintptr",
104-
"C.float": "float32",
105-
"C.double": "float64",
106-
"C._Bool": "bool",
95+
"_Cgo_int8_t": "int8",
96+
"_Cgo_int16_t": "int16",
97+
"_Cgo_int32_t": "int32",
98+
"_Cgo_int64_t": "int64",
99+
"_Cgo_uint8_t": "uint8",
100+
"_Cgo_uint16_t": "uint16",
101+
"_Cgo_uint32_t": "uint32",
102+
"_Cgo_uint64_t": "uint64",
103+
"_Cgo_uintptr_t": "uintptr",
104+
"_Cgo_float": "float32",
105+
"_Cgo_double": "float64",
106+
"_Cgo__Bool": "bool",
107107
}
108108

109109
// builtinAliases are handled specially because they only exist on the Go side
@@ -145,48 +145,46 @@ typedef unsigned long long _Cgo_ulonglong;
145145
// The string/bytes functions below implement C.CString etc. To make sure the
146146
// runtime doesn't need to know the C int type, lengths are converted to uintptr
147147
// first.
148-
// These functions will be modified to get a "C." prefix, so the source below
149-
// doesn't reflect the final AST.
150148
const generatedGoFilePrefixBase = `
151149
import "syscall"
152150
import "unsafe"
153151
154152
var _ unsafe.Pointer
155153
156-
//go:linkname C.CString runtime.cgo_CString
157-
func CString(string) *C.char
154+
//go:linkname _Cgo_CString runtime.cgo_CString
155+
func _Cgo_CString(string) *_Cgo_char
158156
159-
//go:linkname C.GoString runtime.cgo_GoString
160-
func GoString(*C.char) string
157+
//go:linkname _Cgo_GoString runtime.cgo_GoString
158+
func _Cgo_GoString(*_Cgo_char) string
161159
162-
//go:linkname C.__GoStringN runtime.cgo_GoStringN
163-
func __GoStringN(*C.char, uintptr) string
160+
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
161+
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
164162
165-
func GoStringN(cstr *C.char, length C.int) string {
166-
return C.__GoStringN(cstr, uintptr(length))
163+
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
164+
return _Cgo___GoStringN(cstr, uintptr(length))
167165
}
168166
169-
//go:linkname C.__GoBytes runtime.cgo_GoBytes
170-
func __GoBytes(unsafe.Pointer, uintptr) []byte
167+
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
168+
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
171169
172-
func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
173-
return C.__GoBytes(ptr, uintptr(length))
170+
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
171+
return _Cgo___GoBytes(ptr, uintptr(length))
174172
}
175173
176-
//go:linkname C.__CBytes runtime.cgo_CBytes
177-
func __CBytes([]byte) unsafe.Pointer
174+
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
175+
func _Cgo___CBytes([]byte) unsafe.Pointer
178176
179-
func CBytes(b []byte) unsafe.Pointer {
180-
return C.__CBytes(b)
177+
func _Cgo_CBytes(b []byte) unsafe.Pointer {
178+
return _Cgo___CBytes(b)
181179
}
182180
183-
//go:linkname C.__get_errno_num runtime.cgo_errno
184-
func __get_errno_num() uintptr
181+
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
182+
func _Cgo___get_errno_num() uintptr
185183
`
186184

187185
const generatedGoFilePrefixOther = generatedGoFilePrefixBase + `
188-
func __get_errno() error {
189-
return syscall.Errno(C.__get_errno_num())
186+
func _Cgo___get_errno() error {
187+
return syscall.Errno(_Cgo___get_errno_num())
190188
}
191189
`
192190

@@ -197,7 +195,7 @@ func __get_errno() error {
197195
// map the errno values to match the values in the syscall package.
198196
// Source of the errno values: lib/mingw-w64/mingw-w64-headers/crt/errno.h
199197
const generatedGoFilePrefixWindows = generatedGoFilePrefixBase + `
200-
var __errno_mapping = [...]syscall.Errno{
198+
var _Cgo___errno_mapping = [...]syscall.Errno{
201199
1: syscall.EPERM,
202200
2: syscall.ENOENT,
203201
3: syscall.ESRCH,
@@ -238,10 +236,10 @@ var __errno_mapping = [...]syscall.Errno{
238236
42: syscall.EILSEQ,
239237
}
240238
241-
func __get_errno() error {
242-
num := C.__get_errno_num()
243-
if num < uintptr(len(__errno_mapping)) {
244-
if mapped := __errno_mapping[num]; mapped != 0 {
239+
func _Cgo___get_errno() error {
240+
num := _Cgo___get_errno_num()
241+
if num < uintptr(len(_Cgo___errno_mapping)) {
242+
if mapped := _Cgo___errno_mapping[num]; mapped != 0 {
245243
return mapped
246244
}
247245
}
@@ -304,23 +302,6 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
304302
// If the Comments field is not set to nil, the go/format package will get
305303
// confused about where comments should go.
306304
p.generated.Comments = nil
307-
// Adjust some of the functions in there.
308-
for _, decl := range p.generated.Decls {
309-
switch decl := decl.(type) {
310-
case *ast.FuncDecl:
311-
switch decl.Name.Name {
312-
case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes", "CBytes", "__CBytes", "__get_errno_num", "__get_errno", "__errno_mapping":
313-
// Adjust the name to have a "C." prefix so it is correctly
314-
// resolved.
315-
decl.Name.Name = "C." + decl.Name.Name
316-
}
317-
}
318-
}
319-
// Patch some types, for example *C.char in C.CString.
320-
cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
321-
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
322-
return cf.walker(cursor, nil)
323-
}, nil)
324305

325306
// Find `import "C"` C fragments in the file.
326307
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
399380
Tok: token.TYPE,
400381
}
401382
for _, name := range builtinAliases {
402-
typeSpec := p.getIntegerType("C."+name, names["_Cgo_"+name])
383+
typeSpec := p.getIntegerType("_Cgo_"+name, names["_Cgo_"+name])
403384
gen.Specs = append(gen.Specs, typeSpec)
404385
}
405386
p.generated.Decls = append(p.generated.Decls, gen)
@@ -1272,7 +1253,7 @@ func (p *cgoPackage) getUnnamedDeclName(prefix string, itf interface{}) string {
12721253
func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) string {
12731254
// Some types are defined in stdint.h and map directly to a particular Go
12741255
// type.
1275-
if alias := cgoAliases["C."+name]; alias != "" {
1256+
if alias := cgoAliases["_Cgo_"+name]; alias != "" {
12761257
return alias
12771258
}
12781259
node := f.getASTDeclNode(name, found)
@@ -1282,7 +1263,7 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
12821263
}
12831264
return node.Name.Name
12841265
}
1285-
return "C." + name
1266+
return "_Cgo_" + name
12861267
}
12871268

12881269
// getASTDeclNode will declare the given C AST node (if not already defined) and
@@ -1382,8 +1363,8 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
13821363
case *elaboratedTypeInfo:
13831364
// Add struct bitfields.
13841365
for _, bitfield := range elaboratedType.bitfields {
1385-
f.createBitfieldGetter(bitfield, "C."+name)
1386-
f.createBitfieldSetter(bitfield, "C."+name)
1366+
f.createBitfieldGetter(bitfield, "_Cgo_"+name)
1367+
f.createBitfieldSetter(bitfield, "_Cgo_"+name)
13871368
}
13881369
if elaboratedType.unionSize != 0 {
13891370
// Create union getters/setters.
@@ -1392,7 +1373,7 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
13921373
f.addError(elaboratedType.pos, fmt.Sprintf("union must have field with a single name, it has %d names", len(field.Names)))
13931374
continue
13941375
}
1395-
f.createUnionAccessor(field, "C."+name)
1376+
f.createUnionAccessor(field, "_Cgo_"+name)
13961377
}
13971378
}
13981379
}
@@ -1441,7 +1422,7 @@ func (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) b
14411422
node.Rhs = append(node.Rhs, &ast.CallExpr{
14421423
Fun: &ast.Ident{
14431424
NamePos: node.Lhs[1].End(),
1444-
Name: "C.__get_errno",
1425+
Name: "_Cgo___get_errno",
14451426
},
14461427
})
14471428
}
@@ -1466,7 +1447,7 @@ func (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) b
14661447
return true
14671448
}
14681449
if x.Name == "C" {
1469-
name := "C." + node.Sel.Name
1450+
name := "_Cgo_" + node.Sel.Name
14701451
if found, ok := names[node.Sel.Name]; ok {
14711452
name = f.getASTDeclName(node.Sel.Name, found, false)
14721453
}

cgo/libclang.go

+27-27
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
219219
numArgs := int(C.tinygo_clang_Cursor_getNumArguments(c))
220220
obj := &ast.Object{
221221
Kind: ast.Fun,
222-
Name: "C." + name,
222+
Name: "_Cgo_" + name,
223223
}
224224
exportName := name
225225
localName := name
@@ -257,7 +257,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
257257
},
258258
Name: &ast.Ident{
259259
NamePos: pos,
260-
Name: "C." + localName,
260+
Name: "_Cgo_" + localName,
261261
Obj: obj,
262262
},
263263
Type: &ast.FuncType{
@@ -319,7 +319,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
319319
return decl, stringSignature
320320
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
321321
typ := f.makeASTRecordType(c, pos)
322-
typeName := "C." + name
322+
typeName := "_Cgo_" + name
323323
typeExpr := typ.typeExpr
324324
if typ.unionSize != 0 {
325325
// Convert to a single-field struct type.
@@ -340,7 +340,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
340340
obj.Decl = typeSpec
341341
return typeSpec, typ
342342
case C.CXCursor_TypedefDecl:
343-
typeName := "C." + name
343+
typeName := "_Cgo_" + name
344344
underlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(c)
345345
obj := &ast.Object{
346346
Kind: ast.Typ,
@@ -378,12 +378,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
378378
}
379379
obj := &ast.Object{
380380
Kind: ast.Var,
381-
Name: "C." + name,
381+
Name: "_Cgo_" + name,
382382
}
383383
valueSpec := &ast.ValueSpec{
384384
Names: []*ast.Ident{{
385385
NamePos: pos,
386-
Name: "C." + name,
386+
Name: "_Cgo_" + name,
387387
Obj: obj,
388388
}},
389389
Type: typeExpr,
@@ -407,12 +407,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
407407
}
408408
obj := &ast.Object{
409409
Kind: ast.Con,
410-
Name: "C." + name,
410+
Name: "_Cgo_" + name,
411411
}
412412
valueSpec := &ast.ValueSpec{
413413
Names: []*ast.Ident{{
414414
NamePos: pos,
415-
Name: "C." + name,
415+
Name: "_Cgo_" + name,
416416
Obj: obj,
417417
}},
418418
Values: []ast.Expr{expr},
@@ -423,15 +423,15 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
423423
case C.CXCursor_EnumDecl:
424424
obj := &ast.Object{
425425
Kind: ast.Typ,
426-
Name: "C." + name,
426+
Name: "_Cgo_" + name,
427427
}
428428
underlying := C.tinygo_clang_getEnumDeclIntegerType(c)
429429
// TODO: gc's CGo implementation uses types such as `uint32` for enums
430430
// instead of types such as C.int, which are used here.
431431
typeSpec := &ast.TypeSpec{
432432
Name: &ast.Ident{
433433
NamePos: pos,
434-
Name: "C." + name,
434+
Name: "_Cgo_" + name,
435435
Obj: obj,
436436
},
437437
Assign: pos,
@@ -454,12 +454,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
454454
}
455455
obj := &ast.Object{
456456
Kind: ast.Con,
457-
Name: "C." + name,
457+
Name: "_Cgo_" + name,
458458
}
459459
valueSpec := &ast.ValueSpec{
460460
Names: []*ast.Ident{{
461461
NamePos: pos,
462-
Name: "C." + name,
462+
Name: "_Cgo_" + name,
463463
Obj: obj,
464464
}},
465465
Values: []ast.Expr{expr},
@@ -745,27 +745,27 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
745745
var typeName string
746746
switch typ.kind {
747747
case C.CXType_Char_S, C.CXType_Char_U:
748-
typeName = "C.char"
748+
typeName = "_Cgo_char"
749749
case C.CXType_SChar:
750-
typeName = "C.schar"
750+
typeName = "_Cgo_schar"
751751
case C.CXType_UChar:
752-
typeName = "C.uchar"
752+
typeName = "_Cgo_uchar"
753753
case C.CXType_Short:
754-
typeName = "C.short"
754+
typeName = "_Cgo_short"
755755
case C.CXType_UShort:
756-
typeName = "C.ushort"
756+
typeName = "_Cgo_ushort"
757757
case C.CXType_Int:
758-
typeName = "C.int"
758+
typeName = "_Cgo_int"
759759
case C.CXType_UInt:
760-
typeName = "C.uint"
760+
typeName = "_Cgo_uint"
761761
case C.CXType_Long:
762-
typeName = "C.long"
762+
typeName = "_Cgo_long"
763763
case C.CXType_ULong:
764-
typeName = "C.ulong"
764+
typeName = "_Cgo_ulong"
765765
case C.CXType_LongLong:
766-
typeName = "C.longlong"
766+
typeName = "_Cgo_longlong"
767767
case C.CXType_ULongLong:
768-
typeName = "C.ulonglong"
768+
typeName = "_Cgo_ulonglong"
769769
case C.CXType_Bool:
770770
typeName = "bool"
771771
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 {
896896
typeSpelling := getString(C.clang_getTypeSpelling(typ))
897897
typeKindSpelling := getString(C.clang_getTypeKindSpelling(typ.kind))
898898
f.addError(pos, fmt.Sprintf("unknown C type: %v (libclang type kind %s)", typeSpelling, typeKindSpelling))
899-
typeName = "C.<unknown>"
899+
typeName = "_Cgo_<unknown>"
900900
}
901901
return &ast.Ident{
902902
NamePos: pos,
@@ -913,7 +913,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
913913
var goName string
914914
typeSize := C.clang_Type_getSizeOf(underlyingType)
915915
switch name {
916-
case "C.char":
916+
case "_Cgo_char":
917917
if typeSize != 1 {
918918
// This happens for some very special purpose architectures
919919
// (DSPs etc.) that are not currently targeted.
@@ -926,7 +926,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
926926
case C.CXType_Char_U:
927927
goName = "uint8"
928928
}
929-
case "C.schar", "C.short", "C.int", "C.long", "C.longlong":
929+
case "_Cgo_schar", "_Cgo_short", "_Cgo_int", "_Cgo_long", "_Cgo_longlong":
930930
switch typeSize {
931931
case 1:
932932
goName = "int8"
@@ -937,7 +937,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
937937
case 8:
938938
goName = "int64"
939939
}
940-
case "C.uchar", "C.ushort", "C.uint", "C.ulong", "C.ulonglong":
940+
case "_Cgo_uchar", "_Cgo_ushort", "_Cgo_uint", "_Cgo_ulong", "_Cgo_ulonglong":
941941
switch typeSize {
942942
case 1:
943943
goName = "uint8"

0 commit comments

Comments
 (0)