diff options
author | Ayke van Laethem <[email protected]> | 2022-11-27 14:18:22 +0100 |
---|---|---|
committer | Ron Evans <[email protected]> | 2023-09-18 21:58:02 +0200 |
commit | 1d7543e2bfcba3eed51f5340dcaf607d11b0bdeb (patch) | |
tree | 2125653ea6b465f39b05a9d76af9282c255959d2 /cgo | |
parent | ff32fbbb4ff266f5f29080479a29d941cad2a57e (diff) | |
download | tinygo-1d7543e2bfcba3eed51f5340dcaf607d11b0bdeb.tar.gz tinygo-1d7543e2bfcba3eed51f5340dcaf607d11b0bdeb.zip |
all: switch to LLVM 16
This commit adds support for LLVM 16 and switches to it by default. That
means three LLVM versions are supported at the same time: LLVM 14, 15,
and 16.
This commit includes work by QuLogic:
* Part of this work was based on a PR by QuLogic:
https://github.com/tinygo-org/tinygo/pull/3649
But I also had parts of this already implemented in an old branch I
already made for LLVM 16.
* QuLogic also provided a CGo fix here, which is also incorporated in
this commit:
https://github.com/tinygo-org/tinygo/pull/3869
The difference with the original PR by QuLogic is that this commit is
more complete:
* It switches to LLVM 16 by default.
* It updates some things to also make it work with a self-built LLVM.
* It fixes the CGo bug in a slightly different way, and also fixes
another one not included in the original PR.
* It does not keep compiler tests passing on older LLVM versions. I
have found this to be quite burdensome and therefore don't generally
do this - the smoke tests should hopefully catch most regressions.
Diffstat (limited to 'cgo')
-rw-r--r-- | cgo/libclang.go | 18 | ||||
-rw-r--r-- | cgo/libclang_config_llvm15.go | 2 | ||||
-rw-r--r-- | cgo/libclang_config_llvm16.go | 21 | ||||
-rw-r--r-- | cgo/libclang_stubs.c | 6 | ||||
-rw-r--r-- | cgo/testdata/errors.out.go | 4 | ||||
-rw-r--r-- | cgo/testdata/types.out.go | 70 |
6 files changed, 79 insertions, 42 deletions
diff --git a/cgo/libclang.go b/cgo/libclang.go index 27ac1b576..1f2922c56 100644 --- a/cgo/libclang.go +++ b/cgo/libclang.go @@ -60,6 +60,7 @@ CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c); CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c); long long tinygo_clang_getEnumConstantDeclValue(GoCXCursor c); CXType tinygo_clang_getEnumDeclIntegerType(GoCXCursor c); +unsigned tinygo_clang_Cursor_isAnonymous(GoCXCursor c); unsigned tinygo_clang_Cursor_isBitField(GoCXCursor c); int tinygo_clang_globals_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data); @@ -653,8 +654,19 @@ func (p *cgoPackage) addErrorAt(position token.Position, msg string) { func (f *cgoFile) makeDecayingASTType(typ C.CXType, pos token.Pos) ast.Expr { // Strip typedefs, if any. underlyingType := typ + if underlyingType.kind == C.CXType_Elaborated { + // Starting with LLVM 16, the elaborated type is used for more types. + // According to the Clang documentation, the elaborated type has no + // semantic meaning so can be stripped (it is used to better convey type + // name information). + // Source: + // https://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html#details + // > The type itself is always "sugar", used to express what was written + // > in the source code but containing no additional semantic information. + underlyingType = C.clang_Type_getNamedType(underlyingType) + } if underlyingType.kind == C.CXType_Typedef { - c := C.tinygo_clang_getTypeDeclaration(typ) + c := C.tinygo_clang_getTypeDeclaration(underlyingType) underlyingType = C.tinygo_clang_getTypedefDeclUnderlyingType(c) // TODO: support a chain of typedefs. At the moment, it seems to get // stuck in an endless loop when trying to get to the most underlying @@ -788,6 +800,8 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr { return f.makeASTType(underlying, pos) case C.CXType_Enum: return f.makeASTType(underlying, pos) + case C.CXType_Typedef: + return f.makeASTType(underlying, pos) default: typeKindSpelling := getString(C.clang_getTypeKindSpelling(underlying.kind)) f.addError(pos, fmt.Sprintf("unknown elaborated type (libclang type kind %s)", typeKindSpelling)) @@ -806,7 +820,7 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr { // makeASTRecordType will create an appropriate error. cgoRecordPrefix = "record_" } - if name == "" { + if name == "" || C.tinygo_clang_Cursor_isAnonymous(cursor) != 0 { // Anonymous record, probably inside a typedef. location := f.getUniqueLocationID(pos, cursor) name = f.getUnnamedDeclName("_Ctype_"+cgoRecordPrefix+"__", location) diff --git a/cgo/libclang_config_llvm15.go b/cgo/libclang_config_llvm15.go index 32daf0608..e105dfe72 100644 --- a/cgo/libclang_config_llvm15.go +++ b/cgo/libclang_config_llvm15.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !llvm14 +//go:build !byollvm && llvm15 package cgo diff --git a/cgo/libclang_config_llvm16.go b/cgo/libclang_config_llvm16.go new file mode 100644 index 000000000..79aacd2f2 --- /dev/null +++ b/cgo/libclang_config_llvm16.go @@ -0,0 +1,21 @@ +//go:build !byollvm && !llvm14 && !llvm15 + +package cgo + +// As of 2023-05-05, there is a packaging issue on Debian: +// https://github.com/llvm/llvm-project/issues/62199 +// A workaround is to fix this locally, using something like this: +// +// ln -sf ../../x86_64-linux-gnu/libclang-16.so.1 /usr/lib/llvm-16/lib/libclang.so + +/* +#cgo linux CFLAGS: -I/usr/lib/llvm-16/include +#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@16/include +#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@16/include +#cgo freebsd CFLAGS: -I/usr/local/llvm16/include +#cgo linux LDFLAGS: -L/usr/lib/llvm-16/lib -lclang +#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@16/lib -lclang -lffi +#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@16/lib -lclang -lffi +#cgo freebsd LDFLAGS: -L/usr/local/llvm16/lib -lclang +*/ +import "C" diff --git a/cgo/libclang_stubs.c b/cgo/libclang_stubs.c index b0668ed71..1b157d0aa 100644 --- a/cgo/libclang_stubs.c +++ b/cgo/libclang_stubs.c @@ -77,6 +77,10 @@ CXType tinygo_clang_getEnumDeclIntegerType(CXCursor c) { return clang_getEnumDeclIntegerType(c); } +unsigned tinygo_clang_Cursor_isAnonymous(CXCursor c) { + return clang_Cursor_isAnonymous(c); +} + unsigned tinygo_clang_Cursor_isBitField(CXCursor c) { return clang_Cursor_isBitField(c); -}
\ No newline at end of file +} diff --git a/cgo/testdata/errors.out.go b/cgo/testdata/errors.out.go index 716fd771b..b1646a2e0 100644 --- a/cgo/testdata/errors.out.go +++ b/cgo/testdata/errors.out.go @@ -51,10 +51,10 @@ type ( C.longlong int64 C.ulonglong uint64 ) -type C._Ctype_struct___0 struct { +type C.struct_point_t struct { x C.int y C.int } -type C.point_t = C._Ctype_struct___0 +type C.point_t = C.struct_point_t const C.SOME_CONST_3 = 1234 diff --git a/cgo/testdata/types.out.go b/cgo/testdata/types.out.go index bd7b3fc42..a35d3733c 100644 --- a/cgo/testdata/types.out.go +++ b/cgo/testdata/types.out.go @@ -38,11 +38,11 @@ type ( C.ulonglong uint64 ) type C.myint = C.int -type C._Ctype_struct___0 struct { +type C.struct_point2d_t struct { x C.int y C.int } -type C.point2d_t = C._Ctype_struct___0 +type C.point2d_t = C.struct_point2d_t type C.struct_point3d struct { x C.int y C.int @@ -55,21 +55,19 @@ type C.struct_type1 struct { ___type C.int } type C.struct_type2 struct{ _type C.int } -type C._Ctype_union___1 struct{ i C.int } -type C.union1_t = C._Ctype_union___1 -type C._Ctype_union___2 struct{ $union uint64 } +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._Ctype_union___2) unionfield_i() *C.int { - return (*C.int)(unsafe.Pointer(&union.$union)) -} -func (union *C._Ctype_union___2) unionfield_d() *float64 { +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 { return (*float64)(unsafe.Pointer(&union.$union)) } -func (union *C._Ctype_union___2) unionfield_s() *C.short { +func (union *C.union_union3_t) unionfield_s() *C.short { return (*C.short)(unsafe.Pointer(&union.$union)) } -type C.union3_t = C._Ctype_union___2 +type C.union3_t = C.union_union3_t type C.union_union2d struct{ $union [2]uint64 } func (union *C.union_union2d) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) } @@ -78,50 +76,50 @@ func (union *C.union_union2d) unionfield_d() *[2]float64 { } type C.union2d_t = C.union_union2d -type C._Ctype_union___3 struct{ arr [10]C.uchar } -type C.unionarray_t = C._Ctype_union___3 -type C._Ctype_union___5 struct{ $union [3]uint32 } +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 } -func (union *C._Ctype_union___5) unionfield_area() *C.point2d_t { +func (union *C._Ctype_union___0) unionfield_area() *C.point2d_t { return (*C.point2d_t)(unsafe.Pointer(&union.$union)) } -func (union *C._Ctype_union___5) unionfield_solid() *C.point3d_t { +func (union *C._Ctype_union___0) unionfield_solid() *C.point3d_t { return (*C.point3d_t)(unsafe.Pointer(&union.$union)) } -type C._Ctype_struct___4 struct { +type C.struct_struct_nested_t struct { begin C.point2d_t end C.point2d_t tag C.int - coord C._Ctype_union___5 + coord C._Ctype_union___0 } -type C.struct_nested_t = C._Ctype_struct___4 -type C._Ctype_union___6 struct{ $union [2]uint64 } +type C.struct_nested_t = C.struct_struct_nested_t +type C.union_union_nested_t struct{ $union [2]uint64 } -func (union *C._Ctype_union___6) unionfield_point() *C.point3d_t { +func (union *C.union_union_nested_t) unionfield_point() *C.point3d_t { return (*C.point3d_t)(unsafe.Pointer(&union.$union)) } -func (union *C._Ctype_union___6) unionfield_array() *C.unionarray_t { +func (union *C.union_union_nested_t) unionfield_array() *C.unionarray_t { return (*C.unionarray_t)(unsafe.Pointer(&union.$union)) } -func (union *C._Ctype_union___6) unionfield_thing() *C.union3_t { +func (union *C.union_union_nested_t) unionfield_thing() *C.union3_t { return (*C.union3_t)(unsafe.Pointer(&union.$union)) } -type C.union_nested_t = C._Ctype_union___6 +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._Ctype_enum___7 = C.uint -type C.option2_t = C._Ctype_enum___7 -type C._Ctype_struct___8 struct { +type C.enum_option2_t = C.uint +type C.option2_t = C.enum_option2_t +type C.struct_types_t struct { f float32 d float64 ptr *C.int } -type C.types_t = C._Ctype_struct___8 +type C.types_t = C.struct_types_t type C.myIntArray = [10]C.int -type C._Ctype_struct___9 struct { +type C.struct_bitfield_t struct { start C.uchar __bitfield_1 C.uchar @@ -129,21 +127,21 @@ type C._Ctype_struct___9 struct { e C.uchar } -func (s *C._Ctype_struct___9) bitfield_a() C.uchar { return s.__bitfield_1 & 0x1f } -func (s *C._Ctype_struct___9) set_bitfield_a(value C.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) { s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0 } -func (s *C._Ctype_struct___9) bitfield_b() C.uchar { +func (s *C.struct_bitfield_t) bitfield_b() C.uchar { return s.__bitfield_1 >> 5 & 0x1 } -func (s *C._Ctype_struct___9) set_bitfield_b(value C.uchar) { +func (s *C.struct_bitfield_t) set_bitfield_b(value C.uchar) { s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5 } -func (s *C._Ctype_struct___9) bitfield_c() C.uchar { +func (s *C.struct_bitfield_t) bitfield_c() C.uchar { return s.__bitfield_1 >> 6 } -func (s *C._Ctype_struct___9) set_bitfield_c(value C.uchar, +func (s *C.struct_bitfield_t) set_bitfield_c(value C.uchar, ) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 } -type C.bitfield_t = C._Ctype_struct___9 +type C.bitfield_t = C.struct_bitfield_t |