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
8 changes: 4 additions & 4 deletions cl/_testc/struct/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ package foo
import "github.com/goplus/lib/c"

type Foo struct {
U _llcppg_struct_0
U _llcppg_anon_0
Shorts FooShorts
}
type FooShorts struct {
S int16
Us uint16
}
type _llcppg_struct_0 struct {
type _llcppg_anon_0 struct {
X c.Float
Y c.Float
}
type Bar struct {
_llcppg_struct_1
_llcppg_anon_1
}
type _llcppg_struct_1 struct {
type _llcppg_anon_1 struct {
S int16
Us uint16
}
16 changes: 8 additions & 8 deletions cl/_testc/union_struct/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ import (
const XGoPackage = true

type Foo struct {
U _llcppg_union_0
U _llcppg_anon_0
Shorts FooShorts
}
type FooShorts struct {
_xgo_union [1]uint16
}
type _llcppg_union_0 struct {
type _llcppg_anon_0 struct {
_xgo_union [1]float32
}
type Bar struct {
_llcppg_union_1
_llcppg_anon_1
}
type _llcppg_union_1 struct {
type _llcppg_anon_1 struct {
_xgo_union [1]uint16
}

Expand All @@ -30,15 +30,15 @@ func (p *FooShorts) XGof_ref_s() *int16 {
func (p *FooShorts) XGof_ref_us() *uint16 {
return (*uint16)(unsafe.Pointer(p))
}
func (p *_llcppg_union_0) XGof_ref_x() *c.Float {
func (p *_llcppg_anon_0) XGof_ref_x() *c.Float {
return (*c.Float)(unsafe.Pointer(p))
}
func (p *_llcppg_union_0) XGof_ref_y() *c.Float {
func (p *_llcppg_anon_0) XGof_ref_y() *c.Float {
return (*c.Float)(unsafe.Pointer(p))
}
func (p *_llcppg_union_1) XGof_ref_s() *int16 {
func (p *_llcppg_anon_1) XGof_ref_s() *int16 {
return (*int16)(unsafe.Pointer(p))
}
func (p *_llcppg_union_1) XGof_ref_us() *uint16 {
func (p *_llcppg_anon_1) XGof_ref_us() *uint16 {
return (*uint16)(unsafe.Pointer(p))
}
16 changes: 8 additions & 8 deletions cl/_testcpp/class_struct/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,31 @@ package foo
import "github.com/goplus/lib/c"

type Foo struct {
u _llcppg_struct_0
u _llcppg_anon_0
shorts FooShorts
}
type FooShorts struct {
S int16
Us uint16
}
type _llcppg_struct_0 struct {
type _llcppg_anon_0 struct {
X c.Float
Y c.Float
}
type Bar struct {
_llcppg_struct_1
_llcppg_struct_2
_llcppg_struct_3
_llcppg_anon_1
_llcppg_anon_2
_llcppg_anon_3
}
type _llcppg_struct_1 struct {
type _llcppg_anon_1 struct {
S int16
Us uint16
}
type _llcppg_struct_2 struct {
type _llcppg_anon_2 struct {
C c.Char
Uc uint8
}
type _llcppg_struct_3 struct {
type _llcppg_anon_3 struct {
X c.Float
Y c.Float
}
63 changes: 45 additions & 18 deletions cl/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,36 +78,55 @@ func compileClass(ctx *pkgCtx, scope *classCtx) {
}

func loadClass(ctx *pkgCtx, cls clang.Cursor, ns string, kind typeTag) {
if cls.NumTemplateArguments() > 0 {
// TODO(xsw): ignore for now
return
}
origName := nameWithNS(clang.String(cls), ns)
if debugCompileDecl {
log.Println(tagStrvals[kind] + origName)
}
clsName := ctx.typeName(origName, true)
emitClass(ctx, cls, clsName, kind)

var clsName string
var typDecl, ok = ctx.typdecls[origName]
if !ok {
clsName = ctx.typeName(origName, true)
typDecl = newType(ctx, cls, clsName, kind)
ctx.typdecls[origName] = typDecl
}
if cls.IsCursorDefinition() == 0 {
return // declaration only, no definition
}

if clsName == "" {
clsName = ctx.typeName(origName, true)
}
initClassType(ctx, &typDecl, cls, clsName, kind)
}

func emitClass(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) *types.Named {
pkg := ctx.pkg
pkgTypes := pkg.Types
typDefs := pkg.NewTypeDefs()
func newType(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) (ret typDecl) {
ret.defs = ctx.pkg.NewTypeDefs()
ret.TypeDecl = ret.defs.NewType(clsName, goNode(ctx, cls))
ctx.addType(kind, cls, ret.Type())
return
}

func initClassType(ctx *pkgCtx, typDecl *typDecl, cls clang.Cursor, clsName string, kind typeTag) {
// Attach the doc at the TypeDefs (GenDecl) level rather than on the
// TypeSpec; see the note in loadTypedef for why a spec-level doc renders as
// "type// doc" here.
if doc := ctx.docCommentGroup(cls); doc != nil {
typDefs.SetComments(doc)
typDecl.defs.SetComments(doc)
}

typDecl := typDefs.NewType(clsName, goNode(ctx, cls))
typNamed := typDecl.Type()
ctx.addType(kind, cls, typNamed)

scope := &classCtx{
decl: cls,
typNamed: typNamed,
typNamed: typDecl.Type(),
overloads: make(map[string]*overloads),
inPublic: kind == tagStruct,
}
pkg := ctx.pkg
pkgTypes := pkg.Types
clang.VisitChildren(cls, func(decl, parent clang.Cursor) clang.ChildVisitResult {
loadClassMember(ctx, pkgTypes, scope, clsName, decl)
return clang.Continue
Expand All @@ -133,7 +152,12 @@ func emitClass(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) *typ
ctx.addCompileUnit(func(ctx *pkgCtx) {
compileClass(ctx, scope)
})
return typNamed
}

func emitClass(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) *types.Named {
typDecl := newType(ctx, cls, clsName, kind)
initClassType(ctx, &typDecl, cls, clsName, kind)
return typDecl.Type()
}

func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName string, decl clang.Cursor) {
Expand Down Expand Up @@ -168,9 +192,9 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str
if ft.Kind == lc.Type_Record {
if ftd := ft.Declaration(); ftd.IsAnonymous() != 0 {
if ftd.Kind == lc.Cursor_UnionDecl {
fldType = emitUnion(ctx, ftd, ctx.nextAnonUnionName())
fldType = emitUnion(ctx, ftd, ctx.nextAnonName())
} else {
fldType = emitClass(ctx, ftd, ctx.nextAnonStructName(), ftd.Kind)
fldType = emitClass(ctx, ftd, ctx.nextAnonName(), ftd.Kind)
}
anonymous = true
}
Expand Down Expand Up @@ -203,7 +227,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str
loadEnum(ctx, decl, clsName)
}

case lc.Cursor_TypedefDecl:
case lc.Cursor_TypedefDecl, lc.Cursor_TypeAliasDecl:
// A typedef nested in a class acts like one nested in a namespace: it
// only affects naming, so it is emitted as a package-level type alias
// prefixed by the enclosing class name (the class name acts like a
Expand All @@ -225,7 +249,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str
case lc.Cursor_ClassDecl, lc.Cursor_StructDecl:
switch {
case decl.IsAnonymousRecordDecl() != 0:
hoisted := emitClass(ctx, decl, ctx.nextAnonStructName(), decl.Kind)
hoisted := emitClass(ctx, decl, ctx.nextAnonName(), decl.Kind)
fld := types.NewField(goNodePos(ctx, decl), pkg, hoisted.Obj().Name(), hoisted, true)
cls.fields = append(cls.fields, fld)
case decl.IsAnonymous() != 0:
Expand All @@ -244,7 +268,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str
case lc.Cursor_UnionDecl:
switch {
case decl.IsAnonymousRecordDecl() != 0:
hoisted := emitUnion(ctx, decl, ctx.nextAnonUnionName())
hoisted := emitUnion(ctx, decl, ctx.nextAnonName())
fld := types.NewField(goNodePos(ctx, decl), pkg, hoisted.Obj().Name(), hoisted, true)
cls.fields = append(cls.fields, fld)
case decl.IsAnonymous() != 0:
Expand All @@ -256,6 +280,9 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str
loadUnion(ctx, decl, clsName)
}

case lc.Cursor_UnexposedAttr:
// noop

default:
log.Panicln("loadClassMember: unknown kind =", decl.Kind)
}
Expand Down
10 changes: 9 additions & 1 deletion cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ func NewPackage(pkgPath, pkgName string, files []Source, conf *Config) (ret Pack
if rename == nil {
rename = make(map[string]string)
}
typdecls := make(map[string]typDecl)
ctx := &pkgCtx{
overloads: make(map[string]*overloads), pkg: pkg, cb: pkg.CB(),
llgo: llgo, fset: pkg.Fset, c: c, lang: conf.Language,
Expand All @@ -219,14 +220,19 @@ func NewPackage(pkgPath, pkgName string, files []Source, conf *Config) (ret Pack
typeAbbr: conf.TypeAbbr, typePrefix: conf.TypePrefix, fnPrefix: conf.FuncPrefix,
enumPrefix: conf.EnumPrefix, macroPrefix: conf.MacroPrefix, varPrefix: conf.VarPrefix,
nsIgnores: conf.NSIgnore, typeIgnores: conf.TypeIgnore, rename: rename,
classes: conf.Class, nonClasses: conf.NonClass,
classes: conf.Class, nonClasses: conf.NonClass, typdecls: typdecls,
pkgOf: conf.PackageOf, nameLookup: nameLookup, pubLookup: conf.PubFileLookup,
fileBases: make(map[clang.File]int), funcs: make(map[string]*funcObj),
macroVals: make(map[string]any), types: make(map[string]typeObj),
lastSeen: make(map[string]none), impPkgs: make(map[string]none),
}
loadFiles(ctx, files, pkgPath, conf.SourceHeaderFilePrefix, conf.GenMultiGoFiles)
ctx.compile()
for _, typDecl := range typdecls {
if !typDecl.Inited() {
typDecl.InitType(pkg, types.NewStruct(nil, nil))
}
}
ret.Package = pkg
ret.Wrap = ctx.wrap
ret.Public = ctx.pubs
Expand Down Expand Up @@ -305,6 +311,8 @@ func loadDecl(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor, ns string) {
// noop
case lc.Cursor_FunctionTemplate:
// TODO(xsw): ignore for now
case lc.Cursor_ClassTemplate, lc.Cursor_ClassTemplatePartialSpecialization:
// TODO(xsw): ignore for now
default:
log.Panicln("compileDecl: unknown kind =", decl.Kind)
}
Expand Down
34 changes: 12 additions & 22 deletions cl/ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ type typeObj struct {
feats int
}

type typDecl struct {
*gogen.TypeDecl
defs *gogen.TypeDefs
}

type pkgCtx struct {
scopeCtx
pkg *gogen.Package
Expand Down Expand Up @@ -134,39 +139,24 @@ type pkgCtx struct {
impPkgs map[string]none // imported package path set
lastSeen map[string]none // last seen include file set (loaded include files)
thisSeen map[string]none // include file set seen in this translation unit
typdecls map[string]typDecl

compiles []compileUnit
pubs []Entry

// anonUnionSeq is the per-package counter that names tagless inline unions
// hoisted to a Go type "_llcppg_union_<n>", starting at 0 in source order.
// See issue goplus/llcppg#775 (the union proposal's D-series).
anonUnionSeq int
anonStructSeq int
anonSeq int

stdRecvName bool

keepDoc bool
keepDoc bool
}

const (
anonUnionPrefix = "_llcppg_union_"
anonStructPrefix = "_llcppg_struct_"
anonPrefix = "_llcppg_anon_"
)

// nextAnonUnionName returns the next hoisted-union type name
// "_llcppg_union_<n>", incrementing the per-package counter. A tagless inline
// union (with or without a field name) is hoisted to such a type; a tagged or
// named union consumes no number. See issue goplus/llcppg#775.
func (p *pkgCtx) nextAnonUnionName() string {
name := anonUnionPrefix + strconv.Itoa(p.anonUnionSeq)
p.anonUnionSeq++
return name
}

func (p *pkgCtx) nextAnonStructName() string {
name := anonStructPrefix + strconv.Itoa(p.anonStructSeq)
p.anonStructSeq++
func (p *pkgCtx) nextAnonName() string {
name := anonPrefix + strconv.Itoa(p.anonSeq)
p.anonSeq++
return name
}

Expand Down
4 changes: 4 additions & 0 deletions cl/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ func toTypeEx(ctx *pkgCtx, pkg *types.Package, typ lc.Type, flags int, feats *in
// it before recursing so inner arrays are not wrongly decayed.
pointee := toTypeEx(ctx, pkg, elem, flagIsTypeDef, feats)
return newPointer(pointee)
case lc.Type_LValueReference:
Comment thread
xushiwei marked this conversation as resolved.
elem := typ.NonReference()
pointee := toTypeEx(ctx, pkg, elem, flagIsTypeDef, feats)
return newPointer(pointee)
case lc.Type_FunctionProto:
*feats |= featHasCallback
return toFuncType(ctx, pkg, typ, feats)
Expand Down
10 changes: 9 additions & 1 deletion cl/typedef.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func loadTypedef(ctx *pkgCtx, decl clang.Cursor, ns string) {
if debugCompileDecl {
log.Println("typedef", cName, "- ignored")
}
ctx.types[cName] = typeObj{nil, featIgnored}
ctx.types[cName] = typeObj{nil, featIgnored} // ignored
return
}

Expand All @@ -46,6 +46,14 @@ func loadTypedef(ctx *pkgCtx, decl clang.Cursor, ns string) {

feats := 0
tunder := toTypeEx(ctx, pkgTypes, underlying, flagIsTypeDef, &feats)
if feats&featIgnored != 0 {
if debugCompileDecl {
log.Println("typedef", cName, "- ignored")
}
ctx.types[cName] = typeObj{nil, featIgnored} // ignored
return
}

name := ctx.typeName(origName, true)
if tn, ok := tunder.(*types.Named); ok {
if o := tn.Obj(); o.Pkg() == pkgTypes && o.Name() == name {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/goplus/llcppg
go 1.27.0 // llgo 1.0

require (
github.com/goplus/gogen v1.24.9
github.com/goplus/gogen v1.25.1
github.com/goplus/lib v0.5.4
github.com/goplus/mod v0.22.1
github.com/llarhub/clang-c v0.6.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/goplus/gogen v1.24.9 h1:IZnQ/ROLE/uqK5Mm4KW/orvAqcsUSKJZ7AtkqPSQJR4=
github.com/goplus/gogen v1.24.9/go.mod h1:Y7ulYW3wonQ3d9er00b0uGFEV/IUZa6okWJZh892ACQ=
github.com/goplus/gogen v1.25.1 h1:nxNcYVsEy1aNLtXpG1vq8ZGD9qWMK1roUNMkfQ6H9gs=
github.com/goplus/gogen v1.25.1/go.mod h1:Y7ulYW3wonQ3d9er00b0uGFEV/IUZa6okWJZh892ACQ=
github.com/goplus/lib v0.5.4 h1:Ltrj+lY844/jx0nJqCRQEq3YzBkHb3jBjCQZWFUdlTc=
github.com/goplus/lib v0.5.4/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
github.com/goplus/mod v0.22.1 h1:3GQZqKlcQAiMpRUDAHvFryGYie+mT0JMjguEqOtIjkE=
Expand Down
Loading
Loading