diff options
author | Ayke van Laethem <[email protected]> | 2019-04-11 14:03:08 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2019-04-17 11:56:40 +0200 |
commit | 684543b7f15992aea6e2ceb5a8f5be1cda0b29b9 (patch) | |
tree | bb1fa94f257496895d13316b142f57299f85791d /loader | |
parent | bd8e47af809f499057c44663c219d04877cbd6a4 (diff) | |
download | tinygo-684543b7f15992aea6e2ceb5a8f5be1cda0b29b9.tar.gz tinygo-684543b7f15992aea6e2ceb5a8f5be1cda0b29b9.zip |
cgo: implement struct types
Not complete: packed structs are treated as regular structs.
Diffstat (limited to 'loader')
-rw-r--r-- | loader/libclang.go | 68 |
1 files changed, 64 insertions, 4 deletions
diff --git a/loader/libclang.go b/loader/libclang.go index 0b18dbcd4..6f96d212c 100644 --- a/loader/libclang.go +++ b/loader/libclang.go @@ -17,7 +17,8 @@ import ( #include <clang-c/Index.h> // if this fails, install libclang-8-dev #include <stdlib.h> -int tinygo_clang_visitor(CXCursor c, CXCursor parent, CXClientData client_data); +int tinygo_clang_globals_visitor(CXCursor c, CXCursor parent, CXClientData client_data); +int tinygo_clang_struct_visitor(CXCursor c, CXCursor parent, CXClientData client_data); */ import "C" @@ -123,13 +124,13 @@ func (info *fileInfo) parseFragment(fragment string, cflags []string, posFilenam ref := refMap.Put(info) defer refMap.Remove(ref) cursor := C.clang_getTranslationUnitCursor(unit) - C.clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_visitor), C.CXClientData(ref)) + C.clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_globals_visitor), C.CXClientData(ref)) return nil } -//export tinygo_clang_visitor -func tinygo_clang_visitor(c, parent C.CXCursor, client_data C.CXClientData) C.int { +//export tinygo_clang_globals_visitor +func tinygo_clang_globals_visitor(c, parent C.CXCursor, client_data C.CXClientData) C.int { info := refMap.Get(unsafe.Pointer(client_data)).(*fileInfo) kind := C.clang_getCursorKind(c) switch kind { @@ -284,6 +285,34 @@ func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr { Name: "byte", }, } + case C.CXType_Typedef: + typedefName := getString(C.clang_getTypedefName(typ)) + return &ast.Ident{ + NamePos: info.importCPos, + Name: "C." + typedefName, + } + case C.CXType_Elaborated: + underlying := C.clang_Type_getNamedType(typ) + return info.makeASTType(underlying) + case C.CXType_Record: + cursor := C.clang_getTypeDeclaration(typ) + switch C.clang_getCursorKind(cursor) { + case C.CXCursor_StructDecl: + fieldList := &ast.FieldList{ + Opening: info.importCPos, + Closing: info.importCPos, + } + ref := refMap.Put(struct { + fieldList *ast.FieldList + info *fileInfo + }{fieldList, info}) + defer refMap.Remove(ref) + C.clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_struct_visitor), C.CXClientData(uintptr(ref))) + return &ast.StructType{ + Struct: info.importCPos, + Fields: fieldList, + } + } } if typeName == "" { // Fallback, probably incorrect but at least the error points to an odd @@ -295,3 +324,34 @@ func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr { Name: typeName, } } + +//export tinygo_clang_struct_visitor +func tinygo_clang_struct_visitor(c, parent C.CXCursor, client_data C.CXClientData) C.int { + passed := refMap.Get(unsafe.Pointer(client_data)).(struct { + fieldList *ast.FieldList + info *fileInfo + }) + fieldList := passed.fieldList + info := passed.info + if C.clang_getCursorKind(c) != C.CXCursor_FieldDecl { + panic("expected field inside cursor") + } + name := getString(C.clang_getCursorSpelling(c)) + typ := C.clang_getCursorType(c) + field := &ast.Field{ + Type: info.makeASTType(typ), + } + field.Names = []*ast.Ident{ + &ast.Ident{ + NamePos: info.importCPos, + Name: name, + Obj: &ast.Object{ + Kind: ast.Var, + Name: name, + Decl: field, + }, + }, + } + fieldList.List = append(fieldList.List, field) + return C.CXChildVisit_Continue +} |