aboutsummaryrefslogtreecommitdiffhomepage
path: root/loader
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-04-11 14:03:08 +0200
committerRon Evans <[email protected]>2019-04-17 11:56:40 +0200
commit684543b7f15992aea6e2ceb5a8f5be1cda0b29b9 (patch)
treebb1fa94f257496895d13316b142f57299f85791d /loader
parentbd8e47af809f499057c44663c219d04877cbd6a4 (diff)
downloadtinygo-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.go68
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
+}