Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/llgo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- macos-latest
- ubuntu-latest
llvm: [22]
llgo: [v1.0.2]
llgo: [v1.0.3]
go: [1.27]
fail-fast: false
runs-on: ${{matrix.os}}
Expand Down
13 changes: 13 additions & 0 deletions cl/_testcpp/class_with_ns/in.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace bar {
class base
{
public:
~base();
};

class derived
{
private:
base b;
};
}
11 changes: 11 additions & 0 deletions cl/_testcpp/class_with_ns/out.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package foo

type Bar_base struct {
}
type Bar_derived struct {
b Bar_base
}

// llgo:link (*Bar_base).XGo_Dtor C._ZN3bar4baseD1Ev
func (this *Bar_base) XGo_Dtor() {
}
5 changes: 2 additions & 3 deletions cl/_testcpp/ctor_dtor/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@ const (

type Base struct {
}
type Bar struct {
}

// llgo:link (*Base).XGo_Dtor C._ZN4baseD1Ev
func (this *Base) XGo_Dtor() {
}

type Bar struct {
}

// llgo:link (*Bar).XGo_Ctor__1 C._ZN3barC1Ei
func (this *Bar) XGo_Ctor__1(a c.Int) {
}
Expand Down
9 changes: 4 additions & 5 deletions cl/_testcpp/namespace/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ import (

const XGoPackage = true

type Bar_base struct {
}
type Bar_boolean = c.Char

//go:linkname Bar_detail_f__1 C._ZN3bar6detail1fEi
func Bar_detail_f__1(a c.Int) c.Uint

//go:linkname Bar_detail_f__0 C._ZN3bar6detail1fEv
func Bar_detail_f__0()

type Bar_base struct {
}

// llgo:link (*Bar_base).XGo_Dtor C._ZN3bar4baseD1Ev
func (this *Bar_base) XGo_Dtor() {
}

type Bar_boolean = c.Char
32 changes: 16 additions & 16 deletions cl/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,8 @@ type classCtx struct {
inPublic bool
}

func compileClass(ctx *pkgCtx, scope *classCtx, cls clang.Cursor, ns string) {
origName := ns + clang.String(cls)
if debugCompileDecl {
log.Println("class", origName)
}
pkg := ctx.pkg
pkgTypes := pkg.Types
clsName, rewritten := ctx.getPubName(origName, -1)
typDecl := pkg.NewTypeDefs().NewType(clsName, goNode(ctx, cls))
typStruc := types.NewStruct(scope.fields, nil)
typNamed := typDecl.InitType(pkg, typStruc)
if rewritten {
substObj(pkgTypes, pkgTypes.Scope(), origName, typNamed.Obj())
}
func compileClass(ctx *pkgCtx, scope *classCtx) {
scope.reorder()
scope.typNamed = typNamed
for _, method := range scope.publicMethods {
obj := method.obj
if decl := method.outsideDecl; decl.Kind != 0 {
Expand All @@ -71,17 +57,31 @@ func compileClass(ctx *pkgCtx, scope *classCtx, cls clang.Cursor, ns string) {
func loadClass(ctx *pkgCtx, cls clang.Cursor, ns string, defaultInPublic bool) {
pkg := ctx.pkg
pkgTypes := pkg.Types
origName := ns + clang.String(cls)
if debugCompileDecl {
log.Println("class", origName)
}
clsName, rewritten := ctx.getPubName(origName, -1)
typDecl := pkg.NewTypeDefs().NewType(clsName, goNode(ctx, cls))
typNamed := typDecl.Type()
if rewritten {
substObj(pkgTypes, pkgTypes.Scope(), origName, typNamed.Obj())
}
ctx.types[clang.String(cls.Type())] = typNamed
scope := &classCtx{
decl: cls,
typNamed: typNamed,
overloads: make(map[string]*overloads),
inPublic: defaultInPublic,
}
clang.VisitChildren(cls, func(decl, parent clang.Cursor) clang.ChildVisitResult {
loadClassMember(ctx, pkgTypes, scope, decl)
return clang.Continue
})
typStruc := types.NewStruct(scope.fields, nil)
typDecl.InitType(pkg, typStruc)
ctx.compiles = append(ctx.compiles, func(ctx *pkgCtx) {
compileClass(ctx, scope, cls, ns)
compileClass(ctx, scope)
})
}

Expand Down
71 changes: 34 additions & 37 deletions cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ func NewPackage(pkgPath, pkgName string, conf *Config, tu clang.TranslationUnit,
nameLookup = defaultNameLookup
}
ctx := &pkgCtx{
pkg: pkg, cb: pkg.CB(), llgo: llgo, fset: pkg.Fset, tu: tu,
c: c, lang: conf.Language, cflags: conf.CFlags,
wrapFileHeader: conf.WrapFileHeader, nameLookup: nameLookup,
pkg: pkg, cb: pkg.CB(), llgo: llgo, fset: pkg.Fset, tu: tu, c: c, lang: conf.Language,
cflags: conf.CFlags, wrapFileHeader: conf.WrapFileHeader, nameLookup: nameLookup,
methods: make(map[string]*classMethod), macroVals: make(map[string]any),
types: make(map[string]types.Type),
}
ctx.initFiles(files)
loadFiles(ctx)
Expand Down Expand Up @@ -209,44 +209,41 @@ func loadMacro(ctx *pkgCtx, decl clang.Cursor) {
if decl.IsMacroFunctionLike() != 0 {
return
}
ctx.compiles = append(ctx.compiles, func(ctx *pkgCtx) {
origName := clang.String(decl)
tokens, dispose := ctx.tu.Tokenize(decl.Extent())
defer dispose()
if debugCompileDecl {
log.Println("macro", origName, "-", len(tokens), "tokens")
}
if len(tokens) > 1 {
if v, ok := evalConstExpr(ctx, tokens[1:]); ok {
pkg := ctx.pkg
pkgTypes := pkg.Types
ctx.macroVals[origName] = v
name, _ := ctx.getPubName(origName, -1)
pkg.NewConstDefs(pkgTypes.Scope()).New(func(cb *gogen.CodeBuilder) int {
cb.Val(v)
return 1
}, 0, token.NoPos, nil, name)
}
origName := clang.String(decl)
tokens, dispose := ctx.tu.Tokenize(decl.Extent())
defer dispose()
if debugCompileDecl {
log.Println("macro", origName, "-", len(tokens), "tokens")
}
if len(tokens) > 1 {
if v, ok := evalConstExpr(ctx, tokens[1:]); ok {
pkg := ctx.pkg
pkgTypes := pkg.Types
ctx.macroVals[origName] = v
name, _ := ctx.getPubName(origName, -1)
pkg.NewConstDefs(pkgTypes.Scope()).New(func(cb *gogen.CodeBuilder) int {
cb.Val(v)
return 1
}, 0, token.NoPos, nil, name)
}
})
}
}

func loadTypedef(ctx *pkgCtx, decl clang.Cursor, ns string) {
ctx.compiles = append(ctx.compiles, func(ctx *pkgCtx) {
origName := ns + clang.String(decl)
pkg := ctx.pkg
pkgTypes := pkg.Types
underlying := decl.TypedefDeclUnderlyingType()
if debugCompileDecl {
log.Println("typedef", origName, "-", clang.String(underlying))
}
tunder := toType(ctx, pkgTypes, underlying, flagIsTypedef)
name, rewritten := ctx.getPubName(origName, -1)
t := pkg.NewTypeDefs().AliasType(name, tunder)
if rewritten {
pkgTypes.Scope().Insert(types.NewTypeName(token.NoPos, pkgTypes, origName, t))
}
})
pkg := ctx.pkg
pkgTypes := pkg.Types
origName := ns + clang.String(decl)
underlying := decl.TypedefDeclUnderlyingType()
if debugCompileDecl {
log.Println("typedef", origName, "-", clang.String(underlying))
}
tunder := toType(ctx, pkgTypes, underlying, flagIsTypedef)
name, rewritten := ctx.getPubName(origName, -1)
t := pkg.NewTypeDefs().AliasType(name, tunder)
if rewritten {
pkgTypes.Scope().Insert(types.NewTypeName(token.NoPos, pkgTypes, origName, t))
}
ctx.types[clang.String(decl.Type())] = t
}

// -----------------------------------------------------------------------------
2 changes: 2 additions & 0 deletions cl/ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package cl
import (
"go/ast"
"go/token"
"go/types"
"log"
"sort"
"strconv"
Expand Down Expand Up @@ -109,6 +110,7 @@ type pkgCtx struct {

macroVals map[string]any // macroName => value
methods map[string]*classMethod // manglingName => class
types map[string]types.Type // c/c++ fullName => types.Type

compiles []compileFunc

Expand Down
25 changes: 25 additions & 0 deletions cl/type_and_var.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ func toType(ctx *pkgCtx, pkg *types.Package, typ lc.Type, flags int) types.Type
return newPointer(pointee)
case lc.TypeVoid:
return tyVoid
case lc.TypeRecord:
cName := fullTypeName(typ)
log.Println("==> fullTypeName:", cName)
if t, ok := ctx.types[cName]; ok {
return t
}
case lc.TypeElaborated:
Comment thread
xushiwei marked this conversation as resolved.
cName := clang.String(typ.NamedType())
if t, ok := ctx.types[cName]; ok {
return t
}
case lc.TypeFunctionProto:
return toFuncType(ctx, pkg, typ)
default:
Expand All @@ -82,6 +93,20 @@ func toType(ctx *pkgCtx, pkg *types.Package, typ lc.Type, flags int) types.Type
panic("todo: toType " + clang.String(typ))
}

func fullTypeName(typ lc.Type) string {
decl := typ.TypeDeclaration()
name := clang.String(decl)
for {
parent := decl.SemanticParent()
if kind := parent.Kind; kind != lc.CursorNamespace && kind != lc.CursorLastDecl {
break
}
name = clang.String(parent) + "::" + name
decl = parent
}
return name
}

func toFuncType(ctx *pkgCtx, pkg *types.Package, fn lc.Type) *types.Signature {
params, variadic := toFuncParams(ctx, pkg, fn)
results := toFuncResults(ctx, pkg, fn.ResultType())
Expand Down
11 changes: 10 additions & 1 deletion cmd/llcppdump/cppdump.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func dump(node clang.Cursor, ns, presumedFile string) {
return clang.Continue
}
name := ns + clang.String(cur)
log.Println("==>", kind, clang.String(kind), name)
log.Println("==>", kind, clang.String(kind), name, typeOf(cur.Type()))
switch kind {
case lc.CursorFunctionDecl, lc.CursorCXXMethod, lc.CursorConstructor, lc.CursorDestructor:
case lc.CursorClassDecl, lc.CursorNamespace:
Expand All @@ -50,6 +50,15 @@ func dump(node clang.Cursor, ns, presumedFile string) {
})
}

func typeOf(t lc.Type) string {
switch t.Kind {
case lc.TypeElaborated:
return typeOf(t.NamedType())
default:
return clang.String(t)
}
}

func main() {
if len(os.Args) < 2 {
fmt.Println("usage: llcppdump <source-file> [<language>]")
Expand Down
Loading