From d236246b2a67af4f01a47fa9753c9db71359c106 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Fri, 25 Sep 2026 13:38:13 +0800 Subject: [PATCH 1/2] cl Source: add member GoFile --- cl/compile.go | 14 ++++++++++---- cl/compile_test.go | 2 +- tool/dump.go | 2 +- tool/gen.go | 6 +++--- tool/gen_test.go | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index 229d9f43..5501d626 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -88,6 +88,9 @@ type Config struct { // wrapper file (optional). WrapFileHeader string + // DefaultGoFile specifies default file name (optional). + DefaultGoFile string + // NameLookup looks up the archive path for a given mangling name. It returns the // archive path and a boolean indicating whether the lookup was successful. If not // specified, llcppg uses a default lookup function that returns an empty archivePath @@ -138,7 +141,10 @@ type Config struct { // ----------------------------------------------------------------------------- // Source represents a source file to be processed by llcppg. -type Source = clang.TranslationUnit +type Source struct { + TU clang.TranslationUnit + GoFile string +} // NewPackage loads a translation unit and generates a Go package with the given package // path, name and configuration. @@ -155,7 +161,7 @@ func NewPackage(pkgPath, pkgName string, files []Source, conf *Config) (ret Pack NewBuiltin: nil, NodeInterpreter: interp, CanImplicitCast: nil, - DefaultGoFile: "", + DefaultGoFile: conf.DefaultGoFile, } pkg := gogen.NewPackage(pkgPath, pkgName, confGox) pkg.SetRedeclarable(true) @@ -203,9 +209,9 @@ func loadFiles(ctx *pkgCtx, files []Source, myPkgPath string) { pkgOf := ctx.pkgOf scope := &ctx.scopeCtx lastSeen := ctx.lastSeen - for _, tu := range files { + for _, f := range files { ctx.thisSeen = make(map[string]none) // reset for each file - clang.VisitChildren(tu.Cursor(), func(decl, parent clang.Cursor) clang.ChildVisitResult { + clang.VisitChildren(f.TU.Cursor(), func(decl, parent clang.Cursor) clang.ChildVisitResult { if pkgOf != nil { at := clang.PresumedFile(decl.Location()) if _, ok := lastSeen[at]; ok { diff --git a/cl/compile_test.go b/cl/compile_test.go index 33f49d64..ff725828 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -79,7 +79,7 @@ func testFromDir(t *testing.T, sel, relDir string, lang cl.Language) { u := idx.ParseTranslationUnit( clang.DetailedPreprocessingRecord, presumedFile, "-x", cltest.LanguageOf(lang)) defer u.Dispose() - files[i] = u + files[i] = cl.Source{TU: u} u.VisitDiagnostics(func(diag clang.Diagnostic) { fmt.Fprintln(os.Stderr, diag.Format(options)) }) diff --git a/tool/dump.go b/tool/dump.go index ded32f38..cfb0f235 100644 --- a/tool/dump.go +++ b/tool/dump.go @@ -62,6 +62,6 @@ func dumpSources(filenames []string, files []cl.Source) { for i, f := range files { filename := filenames[i] log.Println("==> dump", filename) - Dump(f.Cursor(), "", filepath.Dir(filename)) + Dump(f.TU.Cursor(), "", filepath.Dir(filename)) } } diff --git a/tool/gen.go b/tool/gen.go index 6bc81838..18dd241f 100644 --- a/tool/gen.go +++ b/tool/gen.go @@ -255,7 +255,7 @@ func ParseSources(index clang.Index, headerFiles, includeDirs []string, lang str flags[n+1] = lang files := make([]cl.Source, 0, len(headerFiles)) for tu := range index.ParseTranslationUnits(clang.DetailedPreprocessingRecord, headerFiles, flags...) { - files = append(files, tu) + files = append(files, cl.Source{TU: tu}) tu.VisitDiagnostics(func(diag clang.Diagnostic) { fmt.Fprintln(os.Stderr, diag.Format(options)) }) @@ -265,8 +265,8 @@ func ParseSources(index clang.Index, headerFiles, includeDirs []string, lang str // DisposeSources disposes the given translation units. func DisposeSources(sources []cl.Source) { - for _, tu := range sources { - tu.Dispose() + for _, f := range sources { + f.TU.Dispose() } } diff --git a/tool/gen_test.go b/tool/gen_test.go index e93bbfc8..f3d5a46f 100644 --- a/tool/gen_test.go +++ b/tool/gen_test.go @@ -86,7 +86,7 @@ func testSingleFile(t *testing.T, idx clang.Index, pkgDir, headerDir, headerFile }) const pkgPrefix = "clang/" - files := []cl.Source{u} + files := []cl.Source{{TU: u}} imp := packages.NewImporter(nil, headerDir) pkg, err := cl.NewPackage(pkgPrefix+myPkgName, myPkgName, files, &cl.Config{ Importer: imp, From 58c724809f143c75047c6087743aa2111e7f208b Mon Sep 17 00:00:00 2001 From: xushiwei Date: Fri, 25 Sep 2026 13:52:19 +0800 Subject: [PATCH 2/2] cl: pkg.addCompileUnit; gen multiple Go files --- cl/class.go | 2 +- cl/compile.go | 2 ++ cl/ctx.go | 19 ++++++++++++++++--- cl/func.go | 2 +- cl/union.go | 2 +- cl/var.go | 2 +- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/cl/class.go b/cl/class.go index 9b3fbdc2..8dce763b 100644 --- a/cl/class.go +++ b/cl/class.go @@ -130,7 +130,7 @@ func emitClass(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) *typ } typStruc := types.NewStruct(scope.fields, nil) typDecl.InitType(pkg, typStruc) - ctx.compiles = append(ctx.compiles, func(ctx *pkgCtx) { + ctx.addCompileUnit(func(ctx *pkgCtx) { compileClass(ctx, scope) }) return typNamed diff --git a/cl/compile.go b/cl/compile.go index 5501d626..027dbbc5 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -206,10 +206,12 @@ func defaultNameLookup(manglingName string) (archivePath string, ok bool) { // ----------------------------------------------------------------------------- func loadFiles(ctx *pkgCtx, files []Source, myPkgPath string) { + pkg := ctx.pkg pkgOf := ctx.pkgOf scope := &ctx.scopeCtx lastSeen := ctx.lastSeen for _, f := range files { + pkg.SetCurFile(f.GoFile, true) ctx.thisSeen = make(map[string]none) // reset for each file clang.VisitChildren(f.TU.Cursor(), func(decl, parent clang.Cursor) clang.ChildVisitResult { if pkgOf != nil { diff --git a/cl/ctx.go b/cl/ctx.go index 2a9337d7..76f05bff 100644 --- a/cl/ctx.go +++ b/cl/ctx.go @@ -82,6 +82,10 @@ func (p *nodeInterp) LoadExpr(v ast.Node) string { type none struct{} type compileFunc = func(ctx *pkgCtx) +type compileUnit struct { + fn compileFunc + at *gogen.File +} type pkgCtx struct { scopeCtx @@ -120,7 +124,7 @@ type pkgCtx struct { lastSeen map[string]none // last seen include file set (loaded include files) thisSeen map[string]none // include file set seen in this translation unit - compiles []compileFunc + compiles []compileUnit pubs []Entry // anonUnionSeq is the per-package counter that names tagless inline unions @@ -166,9 +170,18 @@ func (p *pkgCtx) getFileBase(c clang.Cursor, file clang.File) int { return base } +func (p *pkgCtx) addCompileUnit(f compileFunc) { + p.compiles = append(p.compiles, compileUnit{ + fn: f, + at: p.pkg.CurFile(), + }) +} + func (p *pkgCtx) compile() { - for _, compile := range p.compiles { - compile(p) + pkg := p.pkg + for _, c := range p.compiles { + pkg.RestoreCurFile(c.at) + c.fn(p) } } diff --git a/cl/func.go b/cl/func.go index e69fd617..a3af1163 100644 --- a/cl/func.go +++ b/cl/func.go @@ -31,7 +31,7 @@ import ( func loadGlobalFunc(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor, ns string) { name := nameWithNS(clang.String(decl), ns) if obj, ok := scope.addFunc(ctx, name, decl); ok { - ctx.compiles = append(ctx.compiles, func(ctx *pkgCtx) { + ctx.addCompileUnit(func(ctx *pkgCtx) { compileFuncOrMethod(ctx, obj, nil) }) } diff --git a/cl/union.go b/cl/union.go index 5416265f..5a786b39 100644 --- a/cl/union.go +++ b/cl/union.go @@ -109,7 +109,7 @@ func emitUnion(ctx *pkgCtx, decl clang.Cursor, uName string) *types.Named { }) recvPtr := types.NewPointer(typNamed) - ctx.compiles = append(ctx.compiles, func(ctx *pkgCtx) { + ctx.addCompileUnit(func(ctx *pkgCtx) { for _, m := range members { genUnionAccessor(ctx, recvPtr, m) } diff --git a/cl/var.go b/cl/var.go index 74782815..4e9f3eb1 100644 --- a/cl/var.go +++ b/cl/var.go @@ -33,7 +33,7 @@ import ( // handled). Non-static class member variables are fields, not VarDecls, and are // handled separately in loadClassMember. func loadVar(ctx *pkgCtx, decl clang.Cursor, ns string) { - ctx.compiles = append(ctx.compiles, func(ctx *pkgCtx) { + ctx.addCompileUnit(func(ctx *pkgCtx) { compileVar(ctx, decl, ns) }) }