aboutsummaryrefslogtreecommitdiffhomepage
path: root/cgo/libclang.go
diff options
context:
space:
mode:
Diffstat (limited to 'cgo/libclang.go')
-rw-r--r--cgo/libclang.go35
1 files changed, 35 insertions, 0 deletions
diff --git a/cgo/libclang.go b/cgo/libclang.go
index f1ba3baa1..8e9af8a08 100644
--- a/cgo/libclang.go
+++ b/cgo/libclang.go
@@ -4,6 +4,7 @@ package cgo
// modification. It does not touch the AST itself.
import (
+ "crypto/sha512"
"fmt"
"go/ast"
"go/scanner"
@@ -56,6 +57,7 @@ unsigned tinygo_clang_Cursor_isBitField(GoCXCursor c);
int tinygo_clang_globals_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
int tinygo_clang_struct_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
int tinygo_clang_enum_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
+void tinygo_clang_inclusion_visitor(CXFile included_file, CXSourceLocation *inclusion_stack, unsigned include_len, CXClientData client_data);
*/
import "C"
@@ -114,6 +116,7 @@ func (p *cgoPackage) parseFragment(fragment string, cflags []string, posFilename
}
defer C.clang_disposeTranslationUnit(unit)
+ // Report parser and type errors.
if numDiagnostics := int(C.clang_getNumDiagnostics(unit)); numDiagnostics != 0 {
addDiagnostic := func(diagnostic C.CXDiagnostic) {
spelling := getString(C.clang_getDiagnosticSpelling(diagnostic))
@@ -134,10 +137,36 @@ func (p *cgoPackage) parseFragment(fragment string, cflags []string, posFilename
}
}
+ // Extract information required by CGo.
ref := storedRefs.Put(p)
defer storedRefs.Remove(ref)
cursor := C.tinygo_clang_getTranslationUnitCursor(unit)
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_globals_visitor), C.CXClientData(ref))
+
+ // Determine files read during CGo processing, for caching.
+ inclusionCallback := func(includedFile C.CXFile) {
+ // Get full file path.
+ path := getString(C.clang_getFileName(includedFile))
+
+ // Get contents of file (that should be in-memory).
+ size := C.size_t(0)
+ rawData := C.clang_getFileContents(unit, includedFile, &size)
+ if rawData == nil {
+ // Sanity check. This should (hopefully) never trigger.
+ panic("libclang: file contents was not loaded")
+ }
+ data := (*[1 << 24]byte)(unsafe.Pointer(rawData))[:size]
+
+ // Hash the contents if it isn't hashed yet.
+ if _, ok := p.visitedFiles[path]; !ok {
+ // already stored
+ sum := sha512.Sum512_224(data)
+ p.visitedFiles[path] = sum[:]
+ }
+ }
+ inclusionCallbackRef := storedRefs.Put(inclusionCallback)
+ defer storedRefs.Remove(inclusionCallbackRef)
+ C.clang_getInclusions(unit, C.CXInclusionVisitor(C.tinygo_clang_inclusion_visitor), C.CXClientData(inclusionCallbackRef))
}
//export tinygo_clang_globals_visitor
@@ -772,3 +801,9 @@ func tinygo_clang_enum_visitor(c, parent C.GoCXCursor, client_data C.CXClientDat
}
return C.CXChildVisit_Continue
}
+
+//export tinygo_clang_inclusion_visitor
+func tinygo_clang_inclusion_visitor(includedFile C.CXFile, inclusionStack *C.CXSourceLocation, includeLen C.unsigned, clientData C.CXClientData) {
+ callback := storedRefs.Get(unsafe.Pointer(clientData)).(func(C.CXFile))
+ callback(includedFile)
+}