Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

llcppg:refactor by preprocess #164

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c8bd81a
clangutils:ComposeIncludes
luoliwoshang Feb 6, 2025
ed92e21
clangutils:Preprocess
luoliwoshang Feb 6, 2025
abbc1ca
llcppsigfetch:parse after clang -E preprocessed hfile
luoliwoshang Feb 7, 2025
8934ea3
llcppsigfetch:output ast info with new proprocess file & filemap
luoliwoshang Feb 11, 2025
6aac980
gogensig:base convert process with input preprocessed info & filemap
luoliwoshang Feb 11, 2025
8ee09fc
gogensig:temp macro_autogen.go
luoliwoshang Feb 11, 2025
6459121
llcppsigfetch:keep libclang & clang same flag
luoliwoshang Feb 11, 2025
78e1cc9
gogensig:test enum,comment,funcrefer,nested,pubfile,receiver,selfref,…
luoliwoshang Feb 11, 2025
83c90ad
gogensig:test systopkg,cjson,gpgerror,lua,sqlite with rafactor
luoliwoshang Feb 11, 2025
baaf18e
gogensig:refactor process in main logic
luoliwoshang Feb 11, 2025
ed97113
llcppsigfetch:use clang include if exist
luoliwoshang Feb 12, 2025
5739f35
gogensig:avoid node from deppkg convert
luoliwoshang Feb 13, 2025
b315ee7
gogensig:sys file not found panic
luoliwoshang Feb 13, 2025
a2169e3
llcppsigfetch:use clang's searchpath to keep libclang consist
luoliwoshang Feb 13, 2025
1d6b1dd
llcppsigfetch:debug LibClangFlags
luoliwoshang Feb 13, 2025
bab3809
llcppsigfetch:fileMap with keep include's processed file
luoliwoshang Feb 14, 2025
26c40b7
llcppsigfetch:set libclang's resource-dir to keep same flag as clang …
luoliwoshang Feb 14, 2025
602709b
llcppg:collect macro's loc
luoliwoshang Feb 14, 2025
251e28a
gogensig:write macro
luoliwoshang Feb 14, 2025
3060a59
llcppg:dispatch resource-dir
luoliwoshang Feb 14, 2025
8f03b42
llcppg:remove noexist include in test
luoliwoshang Feb 14, 2025
42a7e88
chore:temp rm some test in linux
luoliwoshang Feb 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,11 @@ jobs:
sudo apt install liblua5.4-dev libsqlite3-dev libgmp-dev libgpg-error-dev zlib1g-dev -y
llcppgtest -demo ./_llcppgtest/cjson
llcppgtest -demo ./_llcppgtest/lua
llcppgtest -demo ./_llcppgtest/sqlite
llcppgtest -demo ./_llcppgtest/gmp
llcppgtest -demo ./_llcppgtest/gpgerror
llcppgtest -demo ./_llcppgtest/zlib
# system header err in refactor
# llcppgtest -demo ./_llcppgtest/sqlite
# llcppgtest -demo ./_llcppgtest/gmp
# llcppgtest -demo ./_llcppgtest/gpgerror
# llcppgtest -demo ./_llcppgtest/zlib
- name: Upload coverage reports to Codecov
Expand Down
1 change: 0 additions & 1 deletion _llcppgtest/gettext/llcppg.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"libs": "$(pkg-config --libs glib-2.0) -lgettextpo",
"include": [
"libintl.h",
"autosprintf.h",
"gettext-po.h",
"textstyle.h",
"textstyle/version.h",
Expand Down
3 changes: 1 addition & 2 deletions _llcppgtest/gmp/llcppg.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
"cflags": "$(pkg-config --cflags gmp)",
"libs": "$(pkg-config --libs gmp)",
"include": [
"gmp.h",
"gmpxx.h"
"gmp.h"
],
"deps": null,
"trimPrefixes": ["__"],
Expand Down
2 changes: 1 addition & 1 deletion _llcppgtest/z3/demo/demo/demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func main() {
z3.ModelIncRef(ctx, model)

var val z3.Ast
z3.ModelEval(ctx, model, x, 1, &val)
z3.ModelEval(ctx, model, x, true, &val)
c.Printf(c.Str("find solution: x = %s\n"), z3.AstToString(ctx, val))

z3.ModelDecRef(ctx, model)
Expand Down
1 change: 0 additions & 1 deletion _llcppgtest/z3/llcppg.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"z3_fpa.h",
"z3_optimization.h",
"z3_spacer.h",
"z3_v1.h",
"z3_fixedpoint.h"
],
"trimPrefixes": ["Z3_"],
Expand Down
46 changes: 14 additions & 32 deletions _xtool/llcppsigfetch/llcppsigfetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import (
"github.com/goplus/llcppg/_xtool/llcppsymg/args"
"github.com/goplus/llcppg/_xtool/llcppsymg/clangutils"
"github.com/goplus/llcppg/_xtool/llcppsymg/config"
"github.com/goplus/llcppg/_xtool/llcppsymg/config/cfgparse"
"github.com/goplus/llcppg/_xtool/llcppsymg/syspath"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/cjson"
)
Expand Down Expand Up @@ -75,6 +73,12 @@ func main() {
isTemp = args.BoolArg(arg, false)
case strings.HasPrefix(arg, "-cpp="):
isCpp = args.BoolArg(arg, true)
case strings.HasPrefix(arg, "-ClangResourceDir="):
// temp to avoid call clang in llcppsigfetch,will cause hang
parse.ClangResourceDir = args.StringArg(arg, "")
case strings.HasPrefix(arg, "-ClangSearchPath="):
// temp to avoid call clang in llcppsigfetch,will cause hang
parse.ClangSearchPath = strings.Split(args.StringArg(arg, ""), ",")
default:
otherArgs = append(otherArgs, arg)
}
Expand Down Expand Up @@ -154,33 +158,19 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool, verbose boo
os.Exit(1)
}

cflag := cfgparse.ParseCFlags(conf.CFlags)
files, notFounds, err := cflag.GenHeaderFilePaths(conf.Include, syspath.GetIncludePaths())
check(err)

if verbose {
fmt.Fprintln(os.Stderr, "runFromConfig: header file paths", files)
if len(notFounds) > 0 {
fmt.Fprintln(os.Stderr, "runFromConfig: not found header files", notFounds)
}
}

// Generate include directory flags (-I flags)
incFlags := make([]string, 0, len(cflag.Paths))
for _, path := range cflag.Paths {
incFlags = append(incFlags, "-I"+path)
}

context := parse.NewContext(&parse.ContextConfig{
Conf: conf.Config,
IncFlags: incFlags,
pkg, err := parse.Do(&parse.ParseConfig{
Conf: conf.Config,
})
err = context.ProcessFiles(files)
check(err)

outputInfo(context, outputToFile)
info := parse.MarshalPkg(pkg)
str := info.Print()
defer cjson.FreeCStr(str)
defer info.Delete()
outputResult(str, outputToFile)
}

// todo:use new converter
func runExtract(file string, isTemp bool, isCpp bool, outToFile bool, otherArgs []string, verbose bool) {
cfg := &clangutils.Config{
File: file,
Expand Down Expand Up @@ -219,11 +209,3 @@ func outputResult(result *c.Char, outputToFile bool) {
c.Printf(c.Str("%s"), result)
}
}

func outputInfo(context *parse.Context, outputToFile bool) {
info := context.Output()
str := info.Print()
defer cjson.FreeCStr(str)
defer info.Delete()
outputResult(str, outputToFile)
}
131 changes: 113 additions & 18 deletions _xtool/llcppsigfetch/parse/cvt.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package parse
import (
"fmt"
"os"
"path"
"runtime"
"strings"
"unsafe"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/goplus/llcppg/_xtool/llcppsymg/clangutils"
"github.com/goplus/llcppg/ast"
"github.com/goplus/llcppg/token"
"github.com/goplus/llcppg/types"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/cjson"
"github.com/goplus/llgo/c/clang"
Expand All @@ -22,6 +24,7 @@ type Converter struct {
curLoc ast.Location
index *clang.Index
unit *clang.TranslationUnit
pkg *types.Pkg

indent int // for verbose debug
}
Expand All @@ -34,10 +37,76 @@ var tagMap = map[string]ast.Tag{
}

type Config struct {
File string
Temp bool
Args []string
IsCpp bool
Cfg *clangutils.Config
IncPreprocessedFile string // Which keep origin Include info's processed file
}

func NewConverterX(config *Config) (*Converter, error) {
if dbg.GetDebugParse() {
fmt.Fprintln(os.Stderr, "NewConverter: config")
fmt.Fprintln(os.Stderr, "config.File", config.Cfg.File)
fmt.Fprintln(os.Stderr, "config.Args", config.Cfg.Args)
fmt.Fprintln(os.Stderr, "config.IsCpp", config.Cfg.IsCpp)
fmt.Fprintln(os.Stderr, "config.Temp", config.Cfg.Temp)
}

index, unit, err := clangutils.CreateTranslationUnit(config.Cfg)
if err != nil {
return nil, err
}

fileMap, err := initFileMap(config)
if err != nil {
return nil, err
}
return &Converter{
index: index,
unit: unit,
pkg: &types.Pkg{
File: &ast.File{},
FileMap: fileMap,
},
}, nil
}

// combine file
func initFileMap(cfg *Config) (map[string]*types.FileInfo, error) {
fileMap := make(map[string]*types.FileInfo)
combineConf := cfg.Cfg
combineConf.File = cfg.IncPreprocessedFile
if dbg.GetDebugParse() {
fmt.Fprintln(os.Stderr, "initFileMap: config")
fmt.Fprintln(os.Stderr, "config.File", combineConf.File)
fmt.Fprintln(os.Stderr, "config.Args", combineConf.Args)
fmt.Fprintln(os.Stderr, "config.IsCpp", combineConf.IsCpp)
fmt.Fprintln(os.Stderr, "config.Temp", combineConf.Temp)
}
index, unit, err := clangutils.CreateTranslationUnit(combineConf)
if err != nil {
return nil, err
}
defer index.Dispose()
defer unit.Dispose()
clangutils.VisitChildren(unit.Cursor(), func(cursor, parent clang.Cursor) clang.ChildVisitResult {
if cursor.Kind == clang.CursorInclusionDirective {
name := toStr(cursor.String())
includedFile := cursor.IncludedFile()
includedPath := toStr(includedFile.FileName())
if includedPath == "" {
return clang.ChildVisit_Continue
}

if _, ok := fileMap[includedPath]; !ok {
loc := unit.GetLocation(includedFile, 1, 1)
fileMap[includedPath] = &types.FileInfo{
IsSys: loc.IsInSystemHeader() != 0 || (ClangResourceDir != "" && strings.HasPrefix(includedPath, path.Join(ClangResourceDir, "include"))),
IncPath: name,
}
}
}
return clang.ChildVisit_Continue
})
return fileMap, nil
}

func NewConverter(config *clangutils.Config) (*Converter, error) {
Expand All @@ -60,8 +129,11 @@ func NewConverter(config *clangutils.Config) (*Converter, error) {
Files: files,
index: index,
unit: unit,
pkg: &types.Pkg{
File: &ast.File{},
FileMap: make(map[string]*types.FileInfo),
},
}, nil

}

func (ct *Converter) Dispose() {
Expand Down Expand Up @@ -114,6 +186,7 @@ func (ct *Converter) GetTokens(cursor clang.Cursor) []*ast.Token {
func (ct *Converter) logBase() string {
return strings.Repeat(" ", ct.indent)
}

func (ct *Converter) incIndent() {
ct.indent++
}
Expand Down Expand Up @@ -142,10 +215,10 @@ func (ct *Converter) logln(args ...interface{}) {

func (ct *Converter) GetCurFile(cursor clang.Cursor) *ast.File {
loc := cursor.Location()
var file clang.File
loc.SpellingLocation(&file, nil, nil, nil)
filePath := toStr(file.FileName())
if filePath == "" {
var file clang.String
loc.PresumedLocation(&file, nil, nil)
filePath := clang.GoString(file)
if filePath == "" || filePath == "<command line>" {
//todo(zzy): For some built-in macros, there is no file.
ct.curLoc = ast.Location{File: ""}
ct.logln("GetCurFile: NO FILE")
Expand All @@ -171,9 +244,7 @@ func (ct *Converter) GetCurFile(cursor clang.Cursor) *ast.File {

func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase {
base := ast.DeclBase{
Loc: &ast.Location{
File: ct.curLoc.File,
},
Loc: createLoc(cursor),
Parent: ct.BuildScopingExpr(cursor.SemanticParent()),
}
commentGroup, isDoc := ct.ParseCommentGroup(cursor)
Expand All @@ -183,6 +254,16 @@ func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase {
return base
}

func createLoc(cursor clang.Cursor) *ast.Location {
var file clang.String
loc := cursor.Location()
loc.PresumedLocation(&file, nil, nil)
filename := clang.GoString(file)
return &ast.Location{
File: filename,
}
}

// extracts and parses comments associated with a given Clang cursor,
// distinguishing between documentation comments and line comments.
// It uses libclang to parse only Doxygen-style comments.
Expand Down Expand Up @@ -239,16 +320,20 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
ct.logln(err)
return clang.ChildVisit_Continue
}
ct.pkg.File.Includes = append(ct.pkg.File.Includes, include)
curFile.Includes = append(curFile.Includes, include)
ct.logln("visitTop: ProcessInclude END ", include.Path)
case clang.CursorMacroDefinition:
macro := ct.ProcessMacro(cursor)
curFile.Macros = append(curFile.Macros, macro)
if cursor.Location().IsInSystemHeader() == 0 || cursor.IsMacroBuiltin() != 0 {
ct.pkg.File.Macros = append(ct.pkg.File.Macros, macro)
}
ct.logln("visitTop: ProcessMacro END ", macro.Name, "Tokens Length:", len(macro.Tokens))
case clang.CursorEnumDecl:
enum := ct.ProcessEnumDecl(cursor)
ct.pkg.File.Decls = append(ct.pkg.File.Decls, enum)
curFile.Decls = append(curFile.Decls, enum)

ct.logf("visitTop: ProcessEnumDecl END")
if enum.Name != nil {
ct.logln(enum.Name.Name)
Expand All @@ -259,12 +344,13 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
case clang.CursorClassDecl:
classDecl := ct.ProcessClassDecl(cursor)
curFile.Decls = append(curFile.Decls, classDecl)
ct.pkg.File.Decls = append(ct.pkg.File.Decls, classDecl)
// class havent anonymous situation
ct.logln("visitTop: ProcessClassDecl END", classDecl.Name.Name)
case clang.CursorStructDecl:
structDecl := ct.ProcessStructDecl(cursor)
curFile.Decls = append(curFile.Decls, structDecl)

ct.pkg.File.Decls = append(ct.pkg.File.Decls, structDecl)
ct.logf("visitTop: ProcessStructDecl END")
if structDecl.Name != nil {
ct.logln(structDecl.Name.Name)
Expand All @@ -274,7 +360,7 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
case clang.CursorUnionDecl:
unionDecl := ct.ProcessUnionDecl(cursor)
curFile.Decls = append(curFile.Decls, unionDecl)

ct.pkg.File.Decls = append(ct.pkg.File.Decls, unionDecl)
ct.logf("visitTop: ProcessUnionDecl END")
if unionDecl.Name != nil {
ct.logln(unionDecl.Name.Name)
Expand All @@ -286,13 +372,15 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
// Example: void MyClass::myMethod() { ... } out-of-class method
funcDecl := ct.ProcessFuncDecl(cursor)
curFile.Decls = append(curFile.Decls, funcDecl)
ct.pkg.File.Decls = append(ct.pkg.File.Decls, funcDecl)
ct.logln("visitTop: ProcessFuncDecl END", funcDecl.Name.Name, funcDecl.MangledName, "isStatic:", funcDecl.IsStatic, "isInline:", funcDecl.IsInline)
case clang.CursorTypedefDecl:
typedefDecl := ct.ProcessTypeDefDecl(cursor)
if typedefDecl == nil {
return clang.ChildVisit_Continue
}
curFile.Decls = append(curFile.Decls, typedefDecl)
ct.pkg.File.Decls = append(ct.pkg.File.Decls, typedefDecl)
ct.logln("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name)
case clang.CursorNamespace:
clangutils.VisitChildren(cursor, ct.visitTop)
Expand All @@ -307,6 +395,14 @@ func (ct *Converter) Convert() ([]*ast.FileEntry, error) {
return ct.Files, nil
}

// for flatten ast,keep type order
// input is clang -E 's result
func (ct *Converter) ConvertX() (*types.Pkg, error) {
cursor := ct.unit.Cursor()
clangutils.VisitChildren(cursor, ct.visitTop)
return ct.pkg, nil
}

func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
ct.incIndent()
defer ct.decIndent()
Expand Down Expand Up @@ -645,10 +741,9 @@ func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl {

// current only collect macro which defined in file
func (ct *Converter) ProcessMacro(cursor clang.Cursor) *ast.Macro {
name := toStr(cursor.String())

macro := &ast.Macro{
Name: name,
Loc: createLoc(cursor),
Name: clang.GoString(cursor.String()),
Tokens: ct.GetTokens(cursor),
}
return macro
Expand Down
Loading
Loading