From 9c46ac4eed1356ee3feb7e2e10fcc6c7c8a80103 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 20 Apr 2019 15:10:27 +0200 Subject: [PATCH] cgo: implement char type This type is a bit more difficult because it can be signed or unsigned depending on the target platform. --- loader/cgo.go | 1 + loader/libclang.go | 16 +++++++++++++++- testdata/cgo/main.c | 1 + testdata/cgo/main.go | 1 + testdata/cgo/main.h | 1 + testdata/cgo/out.txt | 1 + 6 files changed, 20 insertions(+), 1 deletion(-) diff --git a/loader/cgo.go b/loader/cgo.go index dc217f96..8cabce7d 100644 --- a/loader/cgo.go +++ b/loader/cgo.go @@ -66,6 +66,7 @@ var cgoAliases = map[string]string{ // somehow from C. This is done by adding some typedefs to get the size of each // type. const cgoTypes = ` +typedef char _Cgo_char; typedef signed char _Cgo_schar; typedef unsigned char _Cgo_uchar; typedef short _Cgo_short; diff --git a/loader/libclang.go b/loader/libclang.go index 4c79fcaf..6166e156 100644 --- a/loader/libclang.go +++ b/loader/libclang.go @@ -203,7 +203,19 @@ func tinygo_clang_globals_visitor(c, parent C.GoCXCursor, client_data C.CXClient expr := expr.(*ast.Ident) typeSize := C.clang_Type_getSizeOf(underlyingType) switch expr.Name { - // TODO: plain char (may be signed or unsigned) + case "C.char": + if typeSize != 1 { + // This happens for some very special purpose architectures + // (DSPs etc.) that are not currently targeted. + // https://www.embecosm.com/2017/04/18/non-8-bit-char-support-in-clang-and-llvm/ + panic("unknown char width") + } + switch underlyingType.kind { + case C.CXType_Char_S: + expr.Name = "int8" + case C.CXType_Char_U: + expr.Name = "uint8" + } case "C.schar", "C.short", "C.int", "C.long", "C.longlong": switch typeSize { case 1: @@ -253,6 +265,8 @@ func getString(clangString C.CXString) (s string) { func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr { var typeName string switch typ.kind { + case C.CXType_Char_S, C.CXType_Char_U: + typeName = "C.char" case C.CXType_SChar: typeName = "C.schar" case C.CXType_UChar: diff --git a/testdata/cgo/main.c b/testdata/cgo/main.c index cec89e47..1d144a02 100644 --- a/testdata/cgo/main.c +++ b/testdata/cgo/main.c @@ -8,6 +8,7 @@ double globalDouble = 3.2; _Complex float globalComplexFloat = 4.1+3.3i; _Complex double globalComplexDouble = 4.2+3.4i; _Complex double globalComplexLongDouble = 4.3+3.5i; +char globalChar = 100; collection_t globalStruct = {256, -123456, 3.14, 88}; int globalStructSize = sizeof(globalStruct); short globalArray[3] = {5, 6, 7}; diff --git a/testdata/cgo/main.go b/testdata/cgo/main.go index b722ce10..ae95943a 100644 --- a/testdata/cgo/main.go +++ b/testdata/cgo/main.go @@ -40,6 +40,7 @@ func main() { println("complex float:", C.globalComplexFloat) println("complex double:", C.globalComplexDouble) println("complex long double:", C.globalComplexLongDouble) + println("char match:", C.globalChar == 100) // complex types println("struct:", C.int(unsafe.Sizeof(C.globalStruct)) == C.globalStructSize, C.globalStruct.s, C.globalStruct.l, C.globalStruct.f) diff --git a/testdata/cgo/main.h b/testdata/cgo/main.h index 4cdf10ea..8c09fe9b 100644 --- a/testdata/cgo/main.h +++ b/testdata/cgo/main.h @@ -36,6 +36,7 @@ extern double globalDouble; extern _Complex float globalComplexFloat; extern _Complex double globalComplexDouble; extern _Complex double globalComplexLongDouble; +extern char globalChar; extern collection_t globalStruct; extern int globalStructSize; extern short globalArray[3]; diff --git a/testdata/cgo/out.txt b/testdata/cgo/out.txt index a5766e6d..df481edf 100644 --- a/testdata/cgo/out.txt +++ b/testdata/cgo/out.txt @@ -14,6 +14,7 @@ double: +3.200000e+000 complex float: (+4.100000e+000+3.300000e+000i) complex double: (+4.200000e+000+3.400000e+000i) complex long double: (+4.300000e+000+3.500000e+000i) +char match: true struct: true 256 -123456 +3.140000e+000 array: 5 6 7 union: true