@@ -16,9 +16,38 @@ import (
1616/*
1717#include <clang-c/Index.h> // if this fails, install libclang-8-dev
1818#include <stdlib.h>
19+ #include <stdint.h>
1920
20- int tinygo_clang_globals_visitor(CXCursor c, CXCursor parent, CXClientData client_data);
21- int tinygo_clang_struct_visitor(CXCursor c, CXCursor parent, CXClientData client_data);
21+ // This struct should be ABI-compatible on all platforms (uintptr_t has the same
22+ // alignment etc. as void*) but does not include void* pointers that are not
23+ // always real pointers.
24+ // The Go garbage collector assumes that all non-nil pointer-typed integers are
25+ // actually pointers. This is not always true, as data[1] often contains 0x1,
26+ // which is clearly not a valid pointer. Usually the GC won't catch this issue,
27+ // but occasionally it will leading to a crash with a vague error message.
28+ typedef struct {
29+ enum CXCursorKind kind;
30+ int xdata;
31+ uintptr_t data[3];
32+ } GoCXCursor;
33+
34+ // Forwarding functions. They are implemented in libclang_stubs.c and forward to
35+ // the real functions without doing anything else, thus they are entirely
36+ // compatible with the versions without tinygo_ prefix. The only difference is
37+ // the CXCursor type, which has been replaced with GoCXCursor.
38+ GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);
39+ unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);
40+ CXString tinygo_clang_getCursorSpelling(GoCXCursor c);
41+ enum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c);
42+ CXType tinygo_clang_getCursorType(GoCXCursor c);
43+ GoCXCursor tinygo_clang_getTypeDeclaration(CXType t);
44+ CXType tinygo_clang_getTypedefDeclUnderlyingType(GoCXCursor c);
45+ CXType tinygo_clang_getCursorResultType(GoCXCursor c);
46+ int tinygo_clang_Cursor_getNumArguments(GoCXCursor c);
47+ GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);
48+
49+ int tinygo_clang_globals_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
50+ int tinygo_clang_struct_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
2251*/
2352import "C"
2453
@@ -123,29 +152,29 @@ func (info *fileInfo) parseFragment(fragment string, cflags []string, posFilenam
123152
124153 ref := refMap .Put (info )
125154 defer refMap .Remove (ref )
126- cursor := C .clang_getTranslationUnitCursor (unit )
127- C .clang_visitChildren (cursor , C .CXCursorVisitor (C .tinygo_clang_globals_visitor ), C .CXClientData (ref ))
155+ cursor := C .tinygo_clang_getTranslationUnitCursor (unit )
156+ C .tinygo_clang_visitChildren (cursor , C .CXCursorVisitor (C .tinygo_clang_globals_visitor ), C .CXClientData (ref ))
128157
129158 return nil
130159}
131160
132161//export tinygo_clang_globals_visitor
133- func tinygo_clang_globals_visitor (c , parent C.CXCursor , client_data C.CXClientData ) C.int {
162+ func tinygo_clang_globals_visitor (c , parent C.GoCXCursor , client_data C.CXClientData ) C.int {
134163 info := refMap .Get (unsafe .Pointer (client_data )).(* fileInfo )
135- kind := C .clang_getCursorKind (c )
164+ kind := C .tinygo_clang_getCursorKind (c )
136165 switch kind {
137166 case C .CXCursor_FunctionDecl :
138- name := getString (C .clang_getCursorSpelling (c ))
139- cursorType := C .clang_getCursorType (c )
167+ name := getString (C .tinygo_clang_getCursorSpelling (c ))
168+ cursorType := C .tinygo_clang_getCursorType (c )
140169 if C .clang_isFunctionTypeVariadic (cursorType ) != 0 {
141170 return C .CXChildVisit_Continue // not supported
142171 }
143- numArgs := int (C .clang_Cursor_getNumArguments (c ))
172+ numArgs := int (C .tinygo_clang_Cursor_getNumArguments (c ))
144173 fn := & functionInfo {}
145174 info .functions [name ] = fn
146175 for i := 0 ; i < numArgs ; i ++ {
147- arg := C .clang_Cursor_getArgument (c , C .uint (i ))
148- argName := getString (C .clang_getCursorSpelling (arg ))
176+ arg := C .tinygo_clang_Cursor_getArgument (c , C .uint (i ))
177+ argName := getString (C .tinygo_clang_getCursorSpelling (arg ))
149178 argType := C .clang_getArgType (cursorType , C .uint (i ))
150179 if argName == "" {
151180 argName = "$" + strconv .Itoa (i )
@@ -155,7 +184,7 @@ func tinygo_clang_globals_visitor(c, parent C.CXCursor, client_data C.CXClientDa
155184 typeExpr : info .makeASTType (argType ),
156185 })
157186 }
158- resultType := C .clang_getCursorResultType (c )
187+ resultType := C .tinygo_clang_getCursorResultType (c )
159188 if resultType .kind != C .CXType_Void {
160189 fn .results = & ast.FieldList {
161190 List : []* ast.Field {
@@ -166,9 +195,9 @@ func tinygo_clang_globals_visitor(c, parent C.CXCursor, client_data C.CXClientDa
166195 }
167196 }
168197 case C .CXCursor_TypedefDecl :
169- typedefType := C .clang_getCursorType (c )
198+ typedefType := C .tinygo_clang_getCursorType (c )
170199 name := getString (C .clang_getTypedefName (typedefType ))
171- underlyingType := C .clang_getTypedefDeclUnderlyingType (c )
200+ underlyingType := C .tinygo_clang_getTypedefDeclUnderlyingType (c )
172201 expr := info .makeASTType (underlyingType )
173202 if strings .HasPrefix (name , "_Cgo_" ) {
174203 expr := expr .(* ast.Ident )
@@ -203,8 +232,8 @@ func tinygo_clang_globals_visitor(c, parent C.CXCursor, client_data C.CXClientDa
203232 typeExpr : expr ,
204233 }
205234 case C .CXCursor_VarDecl :
206- name := getString (C .clang_getCursorSpelling (c ))
207- cursorType := C .clang_getCursorType (c )
235+ name := getString (C .tinygo_clang_getCursorSpelling (c ))
236+ cursorType := C .tinygo_clang_getCursorType (c )
208237 info .globals [name ] = & globalInfo {
209238 typeExpr : info .makeASTType (cursorType ),
210239 }
@@ -305,7 +334,7 @@ func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr {
305334 underlying := C .clang_Type_getNamedType (typ )
306335 return info .makeASTType (underlying )
307336 case C .CXType_Record :
308- cursor := C .clang_getTypeDeclaration (typ )
337+ cursor := C .tinygo_clang_getTypeDeclaration (typ )
309338 fieldList := & ast.FieldList {
310339 Opening : info .importCPos ,
311340 Closing : info .importCPos ,
@@ -315,8 +344,8 @@ func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr {
315344 info * fileInfo
316345 }{fieldList , info })
317346 defer refMap .Remove (ref )
318- C .clang_visitChildren (cursor , C .CXCursorVisitor (C .tinygo_clang_struct_visitor ), C .CXClientData (uintptr ( ref ) ))
319- switch C .clang_getCursorKind (cursor ) {
347+ C .tinygo_clang_visitChildren (cursor , C .CXCursorVisitor (C .tinygo_clang_struct_visitor ), C .CXClientData (ref ))
348+ switch C .tinygo_clang_getCursorKind (cursor ) {
320349 case C .CXCursor_StructDecl :
321350 return & ast.StructType {
322351 Struct : info .importCPos ,
@@ -368,18 +397,18 @@ func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr {
368397}
369398
370399//export tinygo_clang_struct_visitor
371- func tinygo_clang_struct_visitor (c , parent C.CXCursor , client_data C.CXClientData ) C.int {
400+ func tinygo_clang_struct_visitor (c , parent C.GoCXCursor , client_data C.CXClientData ) C.int {
372401 passed := refMap .Get (unsafe .Pointer (client_data )).(struct {
373402 fieldList * ast.FieldList
374403 info * fileInfo
375404 })
376405 fieldList := passed .fieldList
377406 info := passed .info
378- if C .clang_getCursorKind (c ) != C .CXCursor_FieldDecl {
407+ if C .tinygo_clang_getCursorKind (c ) != C .CXCursor_FieldDecl {
379408 panic ("expected field inside cursor" )
380409 }
381- name := getString (C .clang_getCursorSpelling (c ))
382- typ := C .clang_getCursorType (c )
410+ name := getString (C .tinygo_clang_getCursorSpelling (c ))
411+ typ := C .tinygo_clang_getCursorType (c )
383412 field := & ast.Field {
384413 Type : info .makeASTType (typ ),
385414 }
0 commit comments