cgo: refactor
This is a large refactor of the cgo package. It should fix a number of smaller problems and be a bit more strict (like upstream CGo): it for example requires every Go file in a package to include the header files it needs instead of piggybacking on imports in earlier files. The main benefit is that it should be a bit more maintainable and easier to add new features in the future (like static functions). This breaks the tinygo.org/x/bluetooth package, which should be updated before this change lands.
Этот коммит содержится в:
родитель
1d2c39c3b9
коммит
5afb63df60
9 изменённых файлов: 925 добавлений и 945 удалений
896
cgo/cgo.go
896
cgo/cgo.go
Различия файлов не показаны, т.к. их слишком много
Показать различия
582
cgo/libclang.go
582
cgo/libclang.go
|
@ -72,7 +72,11 @@ var diagnosticSeverity = [...]string{
|
||||||
C.CXDiagnostic_Fatal: "fatal",
|
C.CXDiagnostic_Fatal: "fatal",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *cgoPackage) parseFragment(fragment string, cflags []string, filename string) {
|
// Alias so that cgo.go (which doesn't import Clang related stuff and is in
|
||||||
|
// theory decoupled from Clang) can also use this type.
|
||||||
|
type clangCursor = C.GoCXCursor
|
||||||
|
|
||||||
|
func (f *cgoFile) readNames(fragment string, cflags []string, filename string, callback func(map[string]clangCursor)) {
|
||||||
index := C.clang_createIndex(0, 0)
|
index := C.clang_createIndex(0, 0)
|
||||||
defer C.clang_disposeIndex(index)
|
defer C.clang_disposeIndex(index)
|
||||||
|
|
||||||
|
@ -119,8 +123,8 @@ func (p *cgoPackage) parseFragment(fragment string, cflags []string, filename st
|
||||||
spelling := getString(C.clang_getDiagnosticSpelling(diagnostic))
|
spelling := getString(C.clang_getDiagnosticSpelling(diagnostic))
|
||||||
severity := diagnosticSeverity[C.clang_getDiagnosticSeverity(diagnostic)]
|
severity := diagnosticSeverity[C.clang_getDiagnosticSeverity(diagnostic)]
|
||||||
location := C.clang_getDiagnosticLocation(diagnostic)
|
location := C.clang_getDiagnosticLocation(diagnostic)
|
||||||
pos := p.getClangLocationPosition(location, unit)
|
pos := f.getClangLocationPosition(location, unit)
|
||||||
p.addError(pos, severity+": "+spelling)
|
f.addError(pos, severity+": "+spelling)
|
||||||
}
|
}
|
||||||
for i := 0; i < numDiagnostics; i++ {
|
for i := 0; i < numDiagnostics; i++ {
|
||||||
diagnostic := C.clang_getDiagnostic(unit, C.uint(i))
|
diagnostic := C.clang_getDiagnostic(unit, C.uint(i))
|
||||||
|
@ -135,7 +139,7 @@ func (p *cgoPackage) parseFragment(fragment string, cflags []string, filename st
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract information required by CGo.
|
// Extract information required by CGo.
|
||||||
ref := storedRefs.Put(p)
|
ref := storedRefs.Put(f)
|
||||||
defer storedRefs.Remove(ref)
|
defer storedRefs.Remove(ref)
|
||||||
cursor := C.tinygo_clang_getTranslationUnitCursor(unit)
|
cursor := C.tinygo_clang_getTranslationUnitCursor(unit)
|
||||||
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_globals_visitor), C.CXClientData(ref))
|
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_globals_visitor), C.CXClientData(ref))
|
||||||
|
@ -155,35 +159,64 @@ func (p *cgoPackage) parseFragment(fragment string, cflags []string, filename st
|
||||||
data := (*[1 << 24]byte)(unsafe.Pointer(rawData))[:size]
|
data := (*[1 << 24]byte)(unsafe.Pointer(rawData))[:size]
|
||||||
|
|
||||||
// Hash the contents if it isn't hashed yet.
|
// Hash the contents if it isn't hashed yet.
|
||||||
if _, ok := p.visitedFiles[path]; !ok {
|
if _, ok := f.visitedFiles[path]; !ok {
|
||||||
// already stored
|
// already stored
|
||||||
sum := sha512.Sum512_224(data)
|
sum := sha512.Sum512_224(data)
|
||||||
p.visitedFiles[path] = sum[:]
|
f.visitedFiles[path] = sum[:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inclusionCallbackRef := storedRefs.Put(inclusionCallback)
|
inclusionCallbackRef := storedRefs.Put(inclusionCallback)
|
||||||
defer storedRefs.Remove(inclusionCallbackRef)
|
defer storedRefs.Remove(inclusionCallbackRef)
|
||||||
C.clang_getInclusions(unit, C.CXInclusionVisitor(C.tinygo_clang_inclusion_visitor), C.CXClientData(inclusionCallbackRef))
|
C.clang_getInclusions(unit, C.CXInclusionVisitor(C.tinygo_clang_inclusion_visitor), C.CXClientData(inclusionCallbackRef))
|
||||||
|
|
||||||
|
// Do all the C AST operations inside a callback. This makes sure that
|
||||||
|
// libclang related memory is only freed after it is not necessary anymore.
|
||||||
|
callback(f.names)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export tinygo_clang_globals_visitor
|
// Convert the AST node under the given Clang cursor to a Go AST node and return
|
||||||
func tinygo_clang_globals_visitor(c, parent C.GoCXCursor, client_data C.CXClientData) C.int {
|
// it.
|
||||||
p := storedRefs.Get(unsafe.Pointer(client_data)).(*cgoPackage)
|
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaboratedTypeInfo) {
|
||||||
kind := C.tinygo_clang_getCursorKind(c)
|
kind := C.tinygo_clang_getCursorKind(c)
|
||||||
pos := p.getCursorPosition(c)
|
pos := f.getCursorPosition(c)
|
||||||
switch kind {
|
switch kind {
|
||||||
case C.CXCursor_FunctionDecl:
|
case C.CXCursor_FunctionDecl:
|
||||||
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
|
||||||
if _, required := p.missingSymbols[name]; !required {
|
|
||||||
return C.CXChildVisit_Continue
|
|
||||||
}
|
|
||||||
cursorType := C.tinygo_clang_getCursorType(c)
|
cursorType := C.tinygo_clang_getCursorType(c)
|
||||||
numArgs := int(C.tinygo_clang_Cursor_getNumArguments(c))
|
numArgs := int(C.tinygo_clang_Cursor_getNumArguments(c))
|
||||||
fn := &functionInfo{
|
obj := &ast.Object{
|
||||||
pos: pos,
|
Kind: ast.Fun,
|
||||||
variadic: C.clang_isFunctionTypeVariadic(cursorType) != 0,
|
Name: "C." + name,
|
||||||
|
}
|
||||||
|
args := make([]*ast.Field, numArgs)
|
||||||
|
decl := &ast.FuncDecl{
|
||||||
|
Doc: &ast.CommentGroup{
|
||||||
|
List: []*ast.Comment{
|
||||||
|
{
|
||||||
|
Slash: pos - 1,
|
||||||
|
Text: "//export " + name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Name: &ast.Ident{
|
||||||
|
NamePos: pos,
|
||||||
|
Name: "C." + name,
|
||||||
|
Obj: obj,
|
||||||
|
},
|
||||||
|
Type: &ast.FuncType{
|
||||||
|
Func: pos,
|
||||||
|
Params: &ast.FieldList{
|
||||||
|
Opening: pos,
|
||||||
|
List: args,
|
||||||
|
Closing: pos,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if C.clang_isFunctionTypeVariadic(cursorType) != 0 {
|
||||||
|
decl.Doc.List = append(decl.Doc.List, &ast.Comment{
|
||||||
|
Slash: pos - 1,
|
||||||
|
Text: "//go:variadic",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
p.functions[name] = fn
|
|
||||||
for i := 0; i < numArgs; i++ {
|
for i := 0; i < numArgs; i++ {
|
||||||
arg := C.tinygo_clang_Cursor_getArgument(c, C.uint(i))
|
arg := C.tinygo_clang_Cursor_getArgument(c, C.uint(i))
|
||||||
argName := getString(C.tinygo_clang_getCursorSpelling(arg))
|
argName := getString(C.tinygo_clang_getCursorSpelling(arg))
|
||||||
|
@ -191,50 +224,108 @@ func tinygo_clang_globals_visitor(c, parent C.GoCXCursor, client_data C.CXClient
|
||||||
if argName == "" {
|
if argName == "" {
|
||||||
argName = "$" + strconv.Itoa(i)
|
argName = "$" + strconv.Itoa(i)
|
||||||
}
|
}
|
||||||
fn.args = append(fn.args, paramInfo{
|
args[i] = &ast.Field{
|
||||||
name: argName,
|
Names: []*ast.Ident{
|
||||||
typeExpr: p.makeDecayingASTType(argType, pos),
|
{
|
||||||
})
|
NamePos: pos,
|
||||||
|
Name: argName,
|
||||||
|
Obj: &ast.Object{
|
||||||
|
Kind: ast.Var,
|
||||||
|
Name: argName,
|
||||||
|
Decl: decl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: f.makeDecayingASTType(argType, pos),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resultType := C.tinygo_clang_getCursorResultType(c)
|
resultType := C.tinygo_clang_getCursorResultType(c)
|
||||||
if resultType.kind != C.CXType_Void {
|
if resultType.kind != C.CXType_Void {
|
||||||
fn.results = &ast.FieldList{
|
decl.Type.Results = &ast.FieldList{
|
||||||
List: []*ast.Field{
|
List: []*ast.Field{
|
||||||
{
|
{
|
||||||
Type: p.makeASTType(resultType, pos),
|
Type: f.makeASTType(resultType, pos),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case C.CXCursor_StructDecl:
|
obj.Decl = decl
|
||||||
typ := C.tinygo_clang_getCursorType(c)
|
return decl, nil
|
||||||
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
|
||||||
if _, required := p.missingSymbols["struct_"+name]; !required {
|
typ := f.makeASTRecordType(c, pos)
|
||||||
return C.CXChildVisit_Continue
|
typeName := "C." + name
|
||||||
|
typeExpr := typ.typeExpr
|
||||||
|
if typ.unionSize != 0 {
|
||||||
|
// Convert to a single-field struct type.
|
||||||
|
typeExpr = f.makeUnionField(typ)
|
||||||
}
|
}
|
||||||
p.makeASTType(typ, pos)
|
obj := &ast.Object{
|
||||||
|
Kind: ast.Typ,
|
||||||
|
Name: typeName,
|
||||||
|
}
|
||||||
|
typeSpec := &ast.TypeSpec{
|
||||||
|
Name: &ast.Ident{
|
||||||
|
NamePos: typ.pos,
|
||||||
|
Name: typeName,
|
||||||
|
Obj: obj,
|
||||||
|
},
|
||||||
|
Type: typeExpr,
|
||||||
|
}
|
||||||
|
obj.Decl = typeSpec
|
||||||
|
return typeSpec, typ
|
||||||
case C.CXCursor_TypedefDecl:
|
case C.CXCursor_TypedefDecl:
|
||||||
typedefType := C.tinygo_clang_getCursorType(c)
|
typeName := "C." + name
|
||||||
name := getString(C.clang_getTypedefName(typedefType))
|
underlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(c)
|
||||||
if _, required := p.missingSymbols[name]; !required {
|
obj := &ast.Object{
|
||||||
return C.CXChildVisit_Continue
|
Kind: ast.Typ,
|
||||||
|
Name: typeName,
|
||||||
}
|
}
|
||||||
p.makeASTType(typedefType, pos)
|
typeSpec := &ast.TypeSpec{
|
||||||
|
Name: &ast.Ident{
|
||||||
|
NamePos: pos,
|
||||||
|
Name: typeName,
|
||||||
|
Obj: obj,
|
||||||
|
},
|
||||||
|
Type: f.makeASTType(underlyingType, pos),
|
||||||
|
}
|
||||||
|
if underlyingType.kind != C.CXType_Enum {
|
||||||
|
typeSpec.Assign = pos
|
||||||
|
}
|
||||||
|
obj.Decl = typeSpec
|
||||||
|
return typeSpec, nil
|
||||||
case C.CXCursor_VarDecl:
|
case C.CXCursor_VarDecl:
|
||||||
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
|
||||||
if _, required := p.missingSymbols[name]; !required {
|
|
||||||
return C.CXChildVisit_Continue
|
|
||||||
}
|
|
||||||
cursorType := C.tinygo_clang_getCursorType(c)
|
cursorType := C.tinygo_clang_getCursorType(c)
|
||||||
p.globals[name] = globalInfo{
|
typeExpr := f.makeASTType(cursorType, pos)
|
||||||
typeExpr: p.makeASTType(cursorType, pos),
|
gen := &ast.GenDecl{
|
||||||
pos: pos,
|
TokPos: pos,
|
||||||
|
Tok: token.VAR,
|
||||||
|
Lparen: token.NoPos,
|
||||||
|
Rparen: token.NoPos,
|
||||||
|
Doc: &ast.CommentGroup{
|
||||||
|
List: []*ast.Comment{
|
||||||
|
{
|
||||||
|
Slash: pos - 1,
|
||||||
|
Text: "//go:extern " + name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
obj := &ast.Object{
|
||||||
|
Kind: ast.Var,
|
||||||
|
Name: "C." + name,
|
||||||
|
}
|
||||||
|
valueSpec := &ast.ValueSpec{
|
||||||
|
Names: []*ast.Ident{{
|
||||||
|
NamePos: pos,
|
||||||
|
Name: "C." + name,
|
||||||
|
Obj: obj,
|
||||||
|
}},
|
||||||
|
Type: typeExpr,
|
||||||
|
}
|
||||||
|
obj.Decl = valueSpec
|
||||||
|
gen.Specs = append(gen.Specs, valueSpec)
|
||||||
|
return gen, nil
|
||||||
case C.CXCursor_MacroDefinition:
|
case C.CXCursor_MacroDefinition:
|
||||||
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
|
||||||
if _, required := p.missingSymbols[name]; !required {
|
|
||||||
return C.CXChildVisit_Continue
|
|
||||||
}
|
|
||||||
sourceRange := C.tinygo_clang_getCursorExtent(c)
|
sourceRange := C.tinygo_clang_getCursorExtent(c)
|
||||||
start := C.clang_getRangeStart(sourceRange)
|
start := C.clang_getRangeStart(sourceRange)
|
||||||
end := C.clang_getRangeEnd(sourceRange)
|
end := C.clang_getRangeEnd(sourceRange)
|
||||||
|
@ -242,17 +333,17 @@ func tinygo_clang_globals_visitor(c, parent C.GoCXCursor, client_data C.CXClient
|
||||||
var startOffset, endOffset C.unsigned
|
var startOffset, endOffset C.unsigned
|
||||||
C.clang_getExpansionLocation(start, &file, nil, nil, &startOffset)
|
C.clang_getExpansionLocation(start, &file, nil, nil, &startOffset)
|
||||||
if file == nil {
|
if file == nil {
|
||||||
p.addError(pos, "internal error: could not find file where macro is defined")
|
f.addError(pos, "internal error: could not find file where macro is defined")
|
||||||
break
|
return nil, nil
|
||||||
}
|
}
|
||||||
C.clang_getExpansionLocation(end, &endFile, nil, nil, &endOffset)
|
C.clang_getExpansionLocation(end, &endFile, nil, nil, &endOffset)
|
||||||
if file != endFile {
|
if file != endFile {
|
||||||
p.addError(pos, "internal error: expected start and end location of a macro to be in the same file")
|
f.addError(pos, "internal error: expected start and end location of a macro to be in the same file")
|
||||||
break
|
return nil, nil
|
||||||
}
|
}
|
||||||
if startOffset > endOffset {
|
if startOffset > endOffset {
|
||||||
p.addError(pos, "internal error: start offset of macro is after end offset")
|
f.addError(pos, "internal error: start offset of macro is after end offset")
|
||||||
break
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// read file contents and extract the relevant byte range
|
// read file contents and extract the relevant byte range
|
||||||
|
@ -260,31 +351,94 @@ func tinygo_clang_globals_visitor(c, parent C.GoCXCursor, client_data C.CXClient
|
||||||
var size C.size_t
|
var size C.size_t
|
||||||
sourcePtr := C.clang_getFileContents(tu, file, &size)
|
sourcePtr := C.clang_getFileContents(tu, file, &size)
|
||||||
if endOffset >= C.uint(size) {
|
if endOffset >= C.uint(size) {
|
||||||
p.addError(pos, "internal error: end offset of macro lies after end of file")
|
f.addError(pos, "internal error: end offset of macro lies after end of file")
|
||||||
break
|
return nil, nil
|
||||||
}
|
}
|
||||||
source := string(((*[1 << 28]byte)(unsafe.Pointer(sourcePtr)))[startOffset:endOffset:endOffset])
|
source := string(((*[1 << 28]byte)(unsafe.Pointer(sourcePtr)))[startOffset:endOffset:endOffset])
|
||||||
if !strings.HasPrefix(source, name) {
|
if !strings.HasPrefix(source, name) {
|
||||||
p.addError(pos, fmt.Sprintf("internal error: expected macro value to start with %#v, got %#v", name, source))
|
f.addError(pos, fmt.Sprintf("internal error: expected macro value to start with %#v, got %#v", name, source))
|
||||||
break
|
return nil, nil
|
||||||
}
|
}
|
||||||
value := source[len(name):]
|
value := source[len(name):]
|
||||||
// Try to convert this #define into a Go constant expression.
|
// Try to convert this #define into a Go constant expression.
|
||||||
expr, scannerError := parseConst(pos+token.Pos(len(name)), p.fset, value)
|
expr, scannerError := parseConst(pos+token.Pos(len(name)), f.fset, value)
|
||||||
if scannerError != nil {
|
if scannerError != nil {
|
||||||
p.errors = append(p.errors, *scannerError)
|
f.errors = append(f.errors, *scannerError)
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
if expr != nil {
|
|
||||||
// Parsing was successful.
|
gen := &ast.GenDecl{
|
||||||
p.constants[name] = constantInfo{expr, pos}
|
TokPos: token.NoPos,
|
||||||
|
Tok: token.CONST,
|
||||||
|
Lparen: token.NoPos,
|
||||||
|
Rparen: token.NoPos,
|
||||||
}
|
}
|
||||||
|
obj := &ast.Object{
|
||||||
|
Kind: ast.Con,
|
||||||
|
Name: "C." + name,
|
||||||
|
}
|
||||||
|
valueSpec := &ast.ValueSpec{
|
||||||
|
Names: []*ast.Ident{{
|
||||||
|
NamePos: pos,
|
||||||
|
Name: "C." + name,
|
||||||
|
Obj: obj,
|
||||||
|
}},
|
||||||
|
Values: []ast.Expr{expr},
|
||||||
|
}
|
||||||
|
obj.Decl = valueSpec
|
||||||
|
gen.Specs = append(gen.Specs, valueSpec)
|
||||||
|
return gen, nil
|
||||||
case C.CXCursor_EnumDecl:
|
case C.CXCursor_EnumDecl:
|
||||||
// Visit all enums, because the fields may be used even when the enum
|
obj := &ast.Object{
|
||||||
// type itself is not.
|
Kind: ast.Typ,
|
||||||
typ := C.tinygo_clang_getCursorType(c)
|
Name: "C." + name,
|
||||||
p.makeASTType(typ, pos)
|
}
|
||||||
|
underlying := C.tinygo_clang_getEnumDeclIntegerType(c)
|
||||||
|
// TODO: gc's CGo implementation uses types such as `uint32` for enums
|
||||||
|
// instead of types such as C.int, which are used here.
|
||||||
|
typeSpec := &ast.TypeSpec{
|
||||||
|
Name: &ast.Ident{
|
||||||
|
NamePos: pos,
|
||||||
|
Name: "C." + name,
|
||||||
|
Obj: obj,
|
||||||
|
},
|
||||||
|
Assign: pos,
|
||||||
|
Type: f.makeASTType(underlying, pos),
|
||||||
|
}
|
||||||
|
obj.Decl = typeSpec
|
||||||
|
return typeSpec, nil
|
||||||
|
case C.CXCursor_EnumConstantDecl:
|
||||||
|
value := C.tinygo_clang_getEnumConstantDeclValue(c)
|
||||||
|
expr := &ast.BasicLit{
|
||||||
|
ValuePos: pos,
|
||||||
|
Kind: token.INT,
|
||||||
|
Value: strconv.FormatInt(int64(value), 10),
|
||||||
|
}
|
||||||
|
gen := &ast.GenDecl{
|
||||||
|
TokPos: token.NoPos,
|
||||||
|
Tok: token.CONST,
|
||||||
|
Lparen: token.NoPos,
|
||||||
|
Rparen: token.NoPos,
|
||||||
|
}
|
||||||
|
obj := &ast.Object{
|
||||||
|
Kind: ast.Con,
|
||||||
|
Name: "C." + name,
|
||||||
|
}
|
||||||
|
valueSpec := &ast.ValueSpec{
|
||||||
|
Names: []*ast.Ident{{
|
||||||
|
NamePos: pos,
|
||||||
|
Name: "C." + name,
|
||||||
|
Obj: obj,
|
||||||
|
}},
|
||||||
|
Values: []ast.Expr{expr},
|
||||||
|
}
|
||||||
|
obj.Decl = valueSpec
|
||||||
|
gen.Specs = append(gen.Specs, valueSpec)
|
||||||
|
return gen, nil
|
||||||
|
default:
|
||||||
|
f.addError(pos, fmt.Sprintf("internal error: unknown cursor type: %d", kind))
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
return C.CXChildVisit_Continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getString(clangString C.CXString) (s string) {
|
func getString(clangString C.CXString) (s string) {
|
||||||
|
@ -294,6 +448,49 @@ func getString(clangString C.CXString) (s string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export tinygo_clang_globals_visitor
|
||||||
|
func tinygo_clang_globals_visitor(c, parent C.GoCXCursor, client_data C.CXClientData) C.int {
|
||||||
|
f := storedRefs.Get(unsafe.Pointer(client_data)).(*cgoFile)
|
||||||
|
switch C.tinygo_clang_getCursorKind(c) {
|
||||||
|
case C.CXCursor_FunctionDecl:
|
||||||
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
f.names[name] = c
|
||||||
|
case C.CXCursor_StructDecl:
|
||||||
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
if name != "" {
|
||||||
|
f.names["struct_"+name] = c
|
||||||
|
}
|
||||||
|
case C.CXCursor_UnionDecl:
|
||||||
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
if name != "" {
|
||||||
|
f.names["union_"+name] = c
|
||||||
|
}
|
||||||
|
case C.CXCursor_TypedefDecl:
|
||||||
|
typedefType := C.tinygo_clang_getCursorType(c)
|
||||||
|
name := getString(C.clang_getTypedefName(typedefType))
|
||||||
|
f.names[name] = c
|
||||||
|
case C.CXCursor_VarDecl:
|
||||||
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
f.names[name] = c
|
||||||
|
case C.CXCursor_MacroDefinition:
|
||||||
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
f.names[name] = c
|
||||||
|
case C.CXCursor_EnumDecl:
|
||||||
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
if name != "" {
|
||||||
|
// Named enum, which can be referenced from Go using C.enum_foo.
|
||||||
|
f.names["enum_"+name] = c
|
||||||
|
}
|
||||||
|
// The enum fields are in global scope, so recurse to visit them.
|
||||||
|
return C.CXChildVisit_Recurse
|
||||||
|
case C.CXCursor_EnumConstantDecl:
|
||||||
|
// We arrive here because of the "Recurse" above.
|
||||||
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
f.names[name] = c
|
||||||
|
}
|
||||||
|
return C.CXChildVisit_Continue
|
||||||
|
}
|
||||||
|
|
||||||
// getCursorPosition returns a usable token.Pos from a libclang cursor.
|
// getCursorPosition returns a usable token.Pos from a libclang cursor.
|
||||||
func (p *cgoPackage) getCursorPosition(cursor C.GoCXCursor) token.Pos {
|
func (p *cgoPackage) getCursorPosition(cursor C.GoCXCursor) token.Pos {
|
||||||
return p.getClangLocationPosition(C.tinygo_clang_getCursorLocation(cursor), C.tinygo_clang_Cursor_getTranslationUnit(cursor))
|
return p.getClangLocationPosition(C.tinygo_clang_getCursorLocation(cursor), C.tinygo_clang_Cursor_getTranslationUnit(cursor))
|
||||||
|
@ -391,7 +588,7 @@ func (p *cgoPackage) addErrorAt(position token.Position, msg string) {
|
||||||
// makeDecayingASTType does the same as makeASTType but takes care of decaying
|
// makeDecayingASTType does the same as makeASTType but takes care of decaying
|
||||||
// types (arrays in function parameters, etc). It is otherwise identical to
|
// types (arrays in function parameters, etc). It is otherwise identical to
|
||||||
// makeASTType.
|
// makeASTType.
|
||||||
func (p *cgoPackage) makeDecayingASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
func (f *cgoFile) makeDecayingASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
// Strip typedefs, if any.
|
// Strip typedefs, if any.
|
||||||
underlyingType := typ
|
underlyingType := typ
|
||||||
if underlyingType.kind == C.CXType_Typedef {
|
if underlyingType.kind == C.CXType_Typedef {
|
||||||
|
@ -417,15 +614,15 @@ func (p *cgoPackage) makeDecayingASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
pointeeType := C.clang_getElementType(underlyingType)
|
pointeeType := C.clang_getElementType(underlyingType)
|
||||||
return &ast.StarExpr{
|
return &ast.StarExpr{
|
||||||
Star: pos,
|
Star: pos,
|
||||||
X: p.makeASTType(pointeeType, pos),
|
X: f.makeASTType(pointeeType, pos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p.makeASTType(typ, pos)
|
return f.makeASTType(typ, pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeASTType return the ast.Expr for the given libclang type. In other words,
|
// makeASTType return the ast.Expr for the given libclang type. In other words,
|
||||||
// it converts a libclang type to a type in the Go AST.
|
// it converts a libclang type to a type in the Go AST.
|
||||||
func (p *cgoPackage) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
var typeName string
|
var typeName string
|
||||||
switch typ.kind {
|
switch typ.kind {
|
||||||
case C.CXType_Char_S, C.CXType_Char_U:
|
case C.CXType_Char_S, C.CXType_Char_U:
|
||||||
|
@ -486,7 +683,7 @@ func (p *cgoPackage) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
}
|
}
|
||||||
return &ast.StarExpr{
|
return &ast.StarExpr{
|
||||||
Star: pos,
|
Star: pos,
|
||||||
X: p.makeASTType(pointeeType, pos),
|
X: f.makeASTType(pointeeType, pos),
|
||||||
}
|
}
|
||||||
case C.CXType_ConstantArray:
|
case C.CXType_ConstantArray:
|
||||||
return &ast.ArrayType{
|
return &ast.ArrayType{
|
||||||
|
@ -496,7 +693,7 @@ func (p *cgoPackage) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
Kind: token.INT,
|
Kind: token.INT,
|
||||||
Value: strconv.FormatInt(int64(C.clang_getArraySize(typ)), 10),
|
Value: strconv.FormatInt(int64(C.clang_getArraySize(typ)), 10),
|
||||||
},
|
},
|
||||||
Elt: p.makeASTType(C.clang_getElementType(typ), pos),
|
Elt: f.makeASTType(C.clang_getElementType(typ), pos),
|
||||||
}
|
}
|
||||||
case C.CXType_FunctionProto:
|
case C.CXType_FunctionProto:
|
||||||
// Be compatible with gc, which uses the *[0]byte type for function
|
// Be compatible with gc, which uses the *[0]byte type for function
|
||||||
|
@ -517,71 +714,21 @@ func (p *cgoPackage) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
}
|
}
|
||||||
case C.CXType_Typedef:
|
case C.CXType_Typedef:
|
||||||
name := getString(C.clang_getTypedefName(typ))
|
name := getString(C.clang_getTypedefName(typ))
|
||||||
if _, ok := p.typedefs[name]; !ok {
|
c := C.tinygo_clang_getTypeDeclaration(typ)
|
||||||
p.typedefs[name] = nil // don't recurse
|
|
||||||
c := C.tinygo_clang_getTypeDeclaration(typ)
|
|
||||||
underlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(c)
|
|
||||||
expr := p.makeASTType(underlyingType, pos)
|
|
||||||
if strings.HasPrefix(name, "_Cgo_") {
|
|
||||||
expr := expr.(*ast.Ident)
|
|
||||||
typeSize := C.clang_Type_getSizeOf(underlyingType)
|
|
||||||
switch expr.Name {
|
|
||||||
case "C.char":
|
|
||||||
if typeSize != 1 {
|
|
||||||
// This happens for some very special purpose architectures
|
|
||||||
// (DSPs etc.) that are not currently targeted.
|
|
||||||
// https://www.embecosm.com/2017/04/18/non-8-bit-char-support-in-clang-and-llvm/
|
|
||||||
p.addError(pos, fmt.Sprintf("unknown char width: %d", typeSize))
|
|
||||||
}
|
|
||||||
switch underlyingType.kind {
|
|
||||||
case C.CXType_Char_S:
|
|
||||||
expr.Name = "int8"
|
|
||||||
case C.CXType_Char_U:
|
|
||||||
expr.Name = "uint8"
|
|
||||||
}
|
|
||||||
case "C.schar", "C.short", "C.int", "C.long", "C.longlong":
|
|
||||||
switch typeSize {
|
|
||||||
case 1:
|
|
||||||
expr.Name = "int8"
|
|
||||||
case 2:
|
|
||||||
expr.Name = "int16"
|
|
||||||
case 4:
|
|
||||||
expr.Name = "int32"
|
|
||||||
case 8:
|
|
||||||
expr.Name = "int64"
|
|
||||||
}
|
|
||||||
case "C.uchar", "C.ushort", "C.uint", "C.ulong", "C.ulonglong":
|
|
||||||
switch typeSize {
|
|
||||||
case 1:
|
|
||||||
expr.Name = "uint8"
|
|
||||||
case 2:
|
|
||||||
expr.Name = "uint16"
|
|
||||||
case 4:
|
|
||||||
expr.Name = "uint32"
|
|
||||||
case 8:
|
|
||||||
expr.Name = "uint64"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.typedefs[name] = &typedefInfo{
|
|
||||||
typeExpr: expr,
|
|
||||||
pos: pos,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &ast.Ident{
|
return &ast.Ident{
|
||||||
NamePos: pos,
|
NamePos: pos,
|
||||||
Name: "C." + name,
|
Name: f.getASTDeclName(name, c, false),
|
||||||
}
|
}
|
||||||
case C.CXType_Elaborated:
|
case C.CXType_Elaborated:
|
||||||
underlying := C.clang_Type_getNamedType(typ)
|
underlying := C.clang_Type_getNamedType(typ)
|
||||||
switch underlying.kind {
|
switch underlying.kind {
|
||||||
case C.CXType_Record:
|
case C.CXType_Record:
|
||||||
return p.makeASTType(underlying, pos)
|
return f.makeASTType(underlying, pos)
|
||||||
case C.CXType_Enum:
|
case C.CXType_Enum:
|
||||||
return p.makeASTType(underlying, pos)
|
return f.makeASTType(underlying, pos)
|
||||||
default:
|
default:
|
||||||
typeKindSpelling := getString(C.clang_getTypeKindSpelling(underlying.kind))
|
typeKindSpelling := getString(C.clang_getTypeKindSpelling(underlying.kind))
|
||||||
p.addError(pos, fmt.Sprintf("unknown elaborated type (libclang type kind %s)", typeKindSpelling))
|
f.addError(pos, fmt.Sprintf("unknown elaborated type (libclang type kind %s)", typeKindSpelling))
|
||||||
typeName = "<unknown>"
|
typeName = "<unknown>"
|
||||||
}
|
}
|
||||||
case C.CXType_Record:
|
case C.CXType_Record:
|
||||||
|
@ -599,63 +746,46 @@ func (p *cgoPackage) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
}
|
}
|
||||||
if name == "" {
|
if name == "" {
|
||||||
// Anonymous record, probably inside a typedef.
|
// Anonymous record, probably inside a typedef.
|
||||||
typeInfo := p.makeASTRecordType(cursor, pos)
|
clangLocation := C.tinygo_clang_getCursorLocation(cursor)
|
||||||
if typeInfo.bitfields != nil || typeInfo.unionSize != 0 {
|
var file C.CXFile
|
||||||
// This record is a union or is a struct with bitfields, so we
|
var line C.unsigned
|
||||||
// have to declare it as a named type (for getters/setters to
|
var column C.unsigned
|
||||||
// work).
|
C.clang_getFileLocation(clangLocation, &file, &line, &column, nil)
|
||||||
p.anonStructNum++
|
location := token.Position{
|
||||||
cgoName := cgoRecordPrefix + strconv.Itoa(p.anonStructNum)
|
Filename: getString(C.clang_getFileName(file)),
|
||||||
p.elaboratedTypes[cgoName] = typeInfo
|
Line: int(line),
|
||||||
return &ast.Ident{
|
Column: int(column),
|
||||||
NamePos: pos,
|
|
||||||
Name: "C." + cgoName,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return typeInfo.typeExpr
|
if location.Filename == "" || location.Line == 0 {
|
||||||
|
// Not sure when this would happen, but protect from it anyway.
|
||||||
|
f.addError(pos, "could not find file/line information")
|
||||||
|
}
|
||||||
|
name = f.getUnnamedDeclName("_Ctype_"+cgoRecordPrefix+"__", location)
|
||||||
} else {
|
} else {
|
||||||
cgoName := cgoRecordPrefix + name
|
name = cgoRecordPrefix + name
|
||||||
if _, ok := p.elaboratedTypes[cgoName]; !ok {
|
}
|
||||||
p.elaboratedTypes[cgoName] = nil // predeclare (to avoid endless recursion)
|
return &ast.Ident{
|
||||||
p.elaboratedTypes[cgoName] = p.makeASTRecordType(cursor, pos)
|
NamePos: pos,
|
||||||
}
|
Name: f.getASTDeclName(name, cursor, false),
|
||||||
return &ast.Ident{
|
|
||||||
NamePos: pos,
|
|
||||||
Name: "C." + cgoName,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case C.CXType_Enum:
|
case C.CXType_Enum:
|
||||||
cursor := C.tinygo_clang_getTypeDeclaration(typ)
|
cursor := C.tinygo_clang_getTypeDeclaration(typ)
|
||||||
name := getString(C.tinygo_clang_getCursorSpelling(cursor))
|
name := getString(C.tinygo_clang_getCursorSpelling(cursor))
|
||||||
underlying := C.tinygo_clang_getEnumDeclIntegerType(cursor)
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
// anonymous enum
|
name = f.getUnnamedDeclName("_Ctype_enum___", cursor)
|
||||||
ref := storedRefs.Put(p)
|
|
||||||
defer storedRefs.Remove(ref)
|
|
||||||
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_enum_visitor), C.CXClientData(ref))
|
|
||||||
return p.makeASTType(underlying, pos)
|
|
||||||
} else {
|
} else {
|
||||||
// named enum
|
name = "enum_" + name
|
||||||
if _, ok := p.enums[name]; !ok {
|
}
|
||||||
ref := storedRefs.Put(p)
|
return &ast.Ident{
|
||||||
defer storedRefs.Remove(ref)
|
NamePos: pos,
|
||||||
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_enum_visitor), C.CXClientData(ref))
|
Name: f.getASTDeclName(name, cursor, false),
|
||||||
p.enums[name] = enumInfo{
|
|
||||||
typeExpr: p.makeASTType(underlying, pos),
|
|
||||||
pos: pos,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &ast.Ident{
|
|
||||||
NamePos: pos,
|
|
||||||
Name: "C.enum_" + name,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if typeName == "" {
|
if typeName == "" {
|
||||||
// Report this as an error.
|
// Report this as an error.
|
||||||
typeSpelling := getString(C.clang_getTypeSpelling(typ))
|
typeSpelling := getString(C.clang_getTypeSpelling(typ))
|
||||||
typeKindSpelling := getString(C.clang_getTypeKindSpelling(typ.kind))
|
typeKindSpelling := getString(C.clang_getTypeKindSpelling(typ.kind))
|
||||||
p.addError(pos, fmt.Sprintf("unknown C type: %v (libclang type kind %s)", typeSpelling, typeKindSpelling))
|
f.addError(pos, fmt.Sprintf("unknown C type: %v (libclang type kind %s)", typeSpelling, typeKindSpelling))
|
||||||
typeName = "C.<unknown>"
|
typeName = "C.<unknown>"
|
||||||
}
|
}
|
||||||
return &ast.Ident{
|
return &ast.Ident{
|
||||||
|
@ -664,9 +794,80 @@ func (p *cgoPackage) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getIntegerType returns an AST node that defines types such as C.int.
|
||||||
|
func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSpec {
|
||||||
|
pos := p.getCursorPosition(cursor)
|
||||||
|
|
||||||
|
// Find a Go type that matches the size and signedness of the given C type.
|
||||||
|
underlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(cursor)
|
||||||
|
var goName string
|
||||||
|
typeSize := C.clang_Type_getSizeOf(underlyingType)
|
||||||
|
switch name {
|
||||||
|
case "C.char":
|
||||||
|
if typeSize != 1 {
|
||||||
|
// This happens for some very special purpose architectures
|
||||||
|
// (DSPs etc.) that are not currently targeted.
|
||||||
|
// https://www.embecosm.com/2017/04/18/non-8-bit-char-support-in-clang-and-llvm/
|
||||||
|
p.addError(pos, fmt.Sprintf("unknown char width: %d", typeSize))
|
||||||
|
}
|
||||||
|
switch underlyingType.kind {
|
||||||
|
case C.CXType_Char_S:
|
||||||
|
goName = "int8"
|
||||||
|
case C.CXType_Char_U:
|
||||||
|
goName = "uint8"
|
||||||
|
}
|
||||||
|
case "C.schar", "C.short", "C.int", "C.long", "C.longlong":
|
||||||
|
switch typeSize {
|
||||||
|
case 1:
|
||||||
|
goName = "int8"
|
||||||
|
case 2:
|
||||||
|
goName = "int16"
|
||||||
|
case 4:
|
||||||
|
goName = "int32"
|
||||||
|
case 8:
|
||||||
|
goName = "int64"
|
||||||
|
}
|
||||||
|
case "C.uchar", "C.ushort", "C.uint", "C.ulong", "C.ulonglong":
|
||||||
|
switch typeSize {
|
||||||
|
case 1:
|
||||||
|
goName = "uint8"
|
||||||
|
case 2:
|
||||||
|
goName = "uint16"
|
||||||
|
case 4:
|
||||||
|
goName = "uint32"
|
||||||
|
case 8:
|
||||||
|
goName = "uint64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if goName == "" { // should not happen
|
||||||
|
p.addError(pos, "internal error: did not find Go type for C type "+name)
|
||||||
|
goName = "int"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct an *ast.TypeSpec for this type.
|
||||||
|
obj := &ast.Object{
|
||||||
|
Kind: ast.Typ,
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
spec := &ast.TypeSpec{
|
||||||
|
Name: &ast.Ident{
|
||||||
|
NamePos: pos,
|
||||||
|
Name: name,
|
||||||
|
Obj: obj,
|
||||||
|
},
|
||||||
|
Type: &ast.Ident{
|
||||||
|
NamePos: pos,
|
||||||
|
Name: goName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
obj.Decl = spec
|
||||||
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
// makeASTRecordType parses a C record (struct or union) and translates it into
|
// makeASTRecordType parses a C record (struct or union) and translates it into
|
||||||
// a Go struct type.
|
// a Go struct type.
|
||||||
func (p *cgoPackage) makeASTRecordType(cursor C.GoCXCursor, pos token.Pos) *elaboratedTypeInfo {
|
func (f *cgoFile) makeASTRecordType(cursor C.GoCXCursor, pos token.Pos) *elaboratedTypeInfo {
|
||||||
fieldList := &ast.FieldList{
|
fieldList := &ast.FieldList{
|
||||||
Opening: pos,
|
Opening: pos,
|
||||||
Closing: pos,
|
Closing: pos,
|
||||||
|
@ -676,11 +877,11 @@ func (p *cgoPackage) makeASTRecordType(cursor C.GoCXCursor, pos token.Pos) *elab
|
||||||
bitfieldNum := 0
|
bitfieldNum := 0
|
||||||
ref := storedRefs.Put(struct {
|
ref := storedRefs.Put(struct {
|
||||||
fieldList *ast.FieldList
|
fieldList *ast.FieldList
|
||||||
pkg *cgoPackage
|
file *cgoFile
|
||||||
inBitfield *bool
|
inBitfield *bool
|
||||||
bitfieldNum *int
|
bitfieldNum *int
|
||||||
bitfieldList *[]bitfieldInfo
|
bitfieldList *[]bitfieldInfo
|
||||||
}{fieldList, p, &inBitfield, &bitfieldNum, &bitfieldList})
|
}{fieldList, f, &inBitfield, &bitfieldNum, &bitfieldList})
|
||||||
defer storedRefs.Remove(ref)
|
defer storedRefs.Remove(ref)
|
||||||
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_struct_visitor), C.CXClientData(ref))
|
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_struct_visitor), C.CXClientData(ref))
|
||||||
renameFieldKeywords(fieldList)
|
renameFieldKeywords(fieldList)
|
||||||
|
@ -709,13 +910,13 @@ func (p *cgoPackage) makeASTRecordType(cursor C.GoCXCursor, pos token.Pos) *elab
|
||||||
}
|
}
|
||||||
if bitfieldList != nil {
|
if bitfieldList != nil {
|
||||||
// This is valid C... but please don't do this.
|
// This is valid C... but please don't do this.
|
||||||
p.addError(pos, "bitfield in a union is not supported")
|
f.addError(pos, "bitfield in a union is not supported")
|
||||||
}
|
}
|
||||||
typ := C.tinygo_clang_getCursorType(cursor)
|
typ := C.tinygo_clang_getCursorType(cursor)
|
||||||
alignInBytes := int64(C.clang_Type_getAlignOf(typ))
|
alignInBytes := int64(C.clang_Type_getAlignOf(typ))
|
||||||
sizeInBytes := int64(C.clang_Type_getSizeOf(typ))
|
sizeInBytes := int64(C.clang_Type_getSizeOf(typ))
|
||||||
if sizeInBytes == 0 {
|
if sizeInBytes == 0 {
|
||||||
p.addError(pos, "zero-length union is not supported")
|
f.addError(pos, "zero-length union is not supported")
|
||||||
}
|
}
|
||||||
typeInfo.unionSize = sizeInBytes
|
typeInfo.unionSize = sizeInBytes
|
||||||
typeInfo.unionAlign = alignInBytes
|
typeInfo.unionAlign = alignInBytes
|
||||||
|
@ -723,7 +924,7 @@ func (p *cgoPackage) makeASTRecordType(cursor C.GoCXCursor, pos token.Pos) *elab
|
||||||
default:
|
default:
|
||||||
cursorKind := C.tinygo_clang_getCursorKind(cursor)
|
cursorKind := C.tinygo_clang_getCursorKind(cursor)
|
||||||
cursorKindSpelling := getString(C.clang_getCursorKindSpelling(cursorKind))
|
cursorKindSpelling := getString(C.clang_getCursorKindSpelling(cursorKind))
|
||||||
p.addError(pos, fmt.Sprintf("expected StructDecl or UnionDecl, not %s", cursorKindSpelling))
|
f.addError(pos, fmt.Sprintf("expected StructDecl or UnionDecl, not %s", cursorKindSpelling))
|
||||||
return &elaboratedTypeInfo{
|
return &elaboratedTypeInfo{
|
||||||
typeExpr: &ast.StructType{
|
typeExpr: &ast.StructType{
|
||||||
Struct: pos,
|
Struct: pos,
|
||||||
|
@ -737,17 +938,17 @@ func (p *cgoPackage) makeASTRecordType(cursor C.GoCXCursor, pos token.Pos) *elab
|
||||||
func tinygo_clang_struct_visitor(c, parent C.GoCXCursor, client_data C.CXClientData) C.int {
|
func tinygo_clang_struct_visitor(c, parent C.GoCXCursor, client_data C.CXClientData) C.int {
|
||||||
passed := storedRefs.Get(unsafe.Pointer(client_data)).(struct {
|
passed := storedRefs.Get(unsafe.Pointer(client_data)).(struct {
|
||||||
fieldList *ast.FieldList
|
fieldList *ast.FieldList
|
||||||
pkg *cgoPackage
|
file *cgoFile
|
||||||
inBitfield *bool
|
inBitfield *bool
|
||||||
bitfieldNum *int
|
bitfieldNum *int
|
||||||
bitfieldList *[]bitfieldInfo
|
bitfieldList *[]bitfieldInfo
|
||||||
})
|
})
|
||||||
fieldList := passed.fieldList
|
fieldList := passed.fieldList
|
||||||
p := passed.pkg
|
f := passed.file
|
||||||
inBitfield := passed.inBitfield
|
inBitfield := passed.inBitfield
|
||||||
bitfieldNum := passed.bitfieldNum
|
bitfieldNum := passed.bitfieldNum
|
||||||
bitfieldList := passed.bitfieldList
|
bitfieldList := passed.bitfieldList
|
||||||
pos := p.getCursorPosition(c)
|
pos := f.getCursorPosition(c)
|
||||||
switch cursorKind := C.tinygo_clang_getCursorKind(c); cursorKind {
|
switch cursorKind := C.tinygo_clang_getCursorKind(c); cursorKind {
|
||||||
case C.CXCursor_FieldDecl:
|
case C.CXCursor_FieldDecl:
|
||||||
// Expected. This is a regular field.
|
// Expected. This is a regular field.
|
||||||
|
@ -756,7 +957,7 @@ func tinygo_clang_struct_visitor(c, parent C.GoCXCursor, client_data C.CXClientD
|
||||||
return C.CXChildVisit_Continue
|
return C.CXChildVisit_Continue
|
||||||
default:
|
default:
|
||||||
cursorKindSpelling := getString(C.clang_getCursorKindSpelling(cursorKind))
|
cursorKindSpelling := getString(C.clang_getCursorKindSpelling(cursorKind))
|
||||||
p.addError(pos, fmt.Sprintf("expected FieldDecl in struct or union, not %s", cursorKindSpelling))
|
f.addError(pos, fmt.Sprintf("expected FieldDecl in struct or union, not %s", cursorKindSpelling))
|
||||||
return C.CXChildVisit_Continue
|
return C.CXChildVisit_Continue
|
||||||
}
|
}
|
||||||
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
@ -767,14 +968,14 @@ func tinygo_clang_struct_visitor(c, parent C.GoCXCursor, client_data C.CXClientD
|
||||||
}
|
}
|
||||||
typ := C.tinygo_clang_getCursorType(c)
|
typ := C.tinygo_clang_getCursorType(c)
|
||||||
field := &ast.Field{
|
field := &ast.Field{
|
||||||
Type: p.makeASTType(typ, p.getCursorPosition(c)),
|
Type: f.makeASTType(typ, f.getCursorPosition(c)),
|
||||||
}
|
}
|
||||||
offsetof := int64(C.clang_Type_getOffsetOf(C.tinygo_clang_getCursorType(parent), C.CString(name)))
|
offsetof := int64(C.clang_Type_getOffsetOf(C.tinygo_clang_getCursorType(parent), C.CString(name)))
|
||||||
alignOf := int64(C.clang_Type_getAlignOf(typ) * 8)
|
alignOf := int64(C.clang_Type_getAlignOf(typ) * 8)
|
||||||
bitfieldOffset := offsetof % alignOf
|
bitfieldOffset := offsetof % alignOf
|
||||||
if bitfieldOffset != 0 {
|
if bitfieldOffset != 0 {
|
||||||
if C.tinygo_clang_Cursor_isBitField(c) != 1 {
|
if C.tinygo_clang_Cursor_isBitField(c) != 1 {
|
||||||
p.addError(pos, "expected a bitfield")
|
f.addError(pos, "expected a bitfield")
|
||||||
return C.CXChildVisit_Continue
|
return C.CXChildVisit_Continue
|
||||||
}
|
}
|
||||||
if !*inBitfield {
|
if !*inBitfield {
|
||||||
|
@ -821,23 +1022,6 @@ func tinygo_clang_struct_visitor(c, parent C.GoCXCursor, client_data C.CXClientD
|
||||||
return C.CXChildVisit_Continue
|
return C.CXChildVisit_Continue
|
||||||
}
|
}
|
||||||
|
|
||||||
//export tinygo_clang_enum_visitor
|
|
||||||
func tinygo_clang_enum_visitor(c, parent C.GoCXCursor, client_data C.CXClientData) C.int {
|
|
||||||
p := storedRefs.Get(unsafe.Pointer(client_data)).(*cgoPackage)
|
|
||||||
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
|
||||||
pos := p.getCursorPosition(c)
|
|
||||||
value := C.tinygo_clang_getEnumConstantDeclValue(c)
|
|
||||||
p.constants[name] = constantInfo{
|
|
||||||
expr: &ast.BasicLit{
|
|
||||||
ValuePos: pos,
|
|
||||||
Kind: token.INT,
|
|
||||||
Value: strconv.FormatInt(int64(value), 10),
|
|
||||||
},
|
|
||||||
pos: pos,
|
|
||||||
}
|
|
||||||
return C.CXChildVisit_Continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//export tinygo_clang_inclusion_visitor
|
//export tinygo_clang_inclusion_visitor
|
||||||
func tinygo_clang_inclusion_visitor(includedFile C.CXFile, inclusionStack *C.CXSourceLocation, includeLen C.unsigned, clientData C.CXClientData) {
|
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 := storedRefs.Get(unsafe.Pointer(clientData)).(func(C.CXFile))
|
||||||
|
|
33
cgo/testdata/basic.out.go
предоставленный
33
cgo/testdata/basic.out.go
предоставленный
|
@ -24,23 +24,16 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
type C.int16_t = int16
|
type (
|
||||||
type C.int32_t = int32
|
C.char uint8
|
||||||
type C.int64_t = int64
|
C.schar int8
|
||||||
type C.int8_t = int8
|
C.uchar uint8
|
||||||
type C.uint16_t = uint16
|
C.short int16
|
||||||
type C.uint32_t = uint32
|
C.ushort uint16
|
||||||
type C.uint64_t = uint64
|
C.int int32
|
||||||
type C.uint8_t = uint8
|
C.uint uint32
|
||||||
type C.uintptr_t = uintptr
|
C.long int32
|
||||||
type C.char uint8
|
C.ulong uint32
|
||||||
type C.int int32
|
C.longlong int64
|
||||||
type C.long int32
|
C.ulonglong uint64
|
||||||
type C.longlong int64
|
)
|
||||||
type C.schar int8
|
|
||||||
type C.short int16
|
|
||||||
type C.uchar uint8
|
|
||||||
type C.uint uint32
|
|
||||||
type C.ulong uint32
|
|
||||||
type C.ulonglong uint64
|
|
||||||
type C.ushort uint16
|
|
||||||
|
|
37
cgo/testdata/const.out.go
предоставленный
37
cgo/testdata/const.out.go
предоставленный
|
@ -24,26 +24,19 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
const C.bar = C.foo
|
type (
|
||||||
const C.foo = 3
|
C.char uint8
|
||||||
|
C.schar int8
|
||||||
|
C.uchar uint8
|
||||||
|
C.short int16
|
||||||
|
C.ushort uint16
|
||||||
|
C.int int32
|
||||||
|
C.uint uint32
|
||||||
|
C.long int32
|
||||||
|
C.ulong uint32
|
||||||
|
C.longlong int64
|
||||||
|
C.ulonglong uint64
|
||||||
|
)
|
||||||
|
|
||||||
type C.int16_t = int16
|
const C.foo = 3
|
||||||
type C.int32_t = int32
|
const C.bar = C.foo
|
||||||
type C.int64_t = int64
|
|
||||||
type C.int8_t = int8
|
|
||||||
type C.uint16_t = uint16
|
|
||||||
type C.uint32_t = uint32
|
|
||||||
type C.uint64_t = uint64
|
|
||||||
type C.uint8_t = uint8
|
|
||||||
type C.uintptr_t = uintptr
|
|
||||||
type C.char uint8
|
|
||||||
type C.int int32
|
|
||||||
type C.long int32
|
|
||||||
type C.longlong int64
|
|
||||||
type C.schar int8
|
|
||||||
type C.short int16
|
|
||||||
type C.uchar uint8
|
|
||||||
type C.uint uint32
|
|
||||||
type C.ulong uint32
|
|
||||||
type C.ulonglong uint64
|
|
||||||
type C.ushort uint16
|
|
||||||
|
|
2
cgo/testdata/errors.go
предоставленный
2
cgo/testdata/errors.go
предоставленный
|
@ -27,7 +27,7 @@ import "C"
|
||||||
//line errors.go:100
|
//line errors.go:100
|
||||||
var (
|
var (
|
||||||
// constant too large
|
// constant too large
|
||||||
_ C.uint8_t = 2 << 10
|
_ C.char = 2 << 10
|
||||||
|
|
||||||
// z member does not exist
|
// z member does not exist
|
||||||
_ C.point_t = C.point_t{z: 3}
|
_ C.point_t = C.point_t{z: 3}
|
||||||
|
|
42
cgo/testdata/errors.out.go
предоставленный
42
cgo/testdata/errors.out.go
предоставленный
|
@ -6,7 +6,7 @@
|
||||||
// testdata/errors.go:19:26: unexpected token ), expected end of expression
|
// testdata/errors.go:19:26: unexpected token ), expected end of expression
|
||||||
|
|
||||||
// Type checking errors after CGo processing:
|
// Type checking errors after CGo processing:
|
||||||
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as uint8 value in variable declaration (overflows)
|
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as C.char value in variable declaration (overflows)
|
||||||
// testdata/errors.go:105: unknown field z in struct literal
|
// testdata/errors.go:105: unknown field z in struct literal
|
||||||
// testdata/errors.go:108: undeclared name: C.SOME_CONST_1
|
// testdata/errors.go:108: undeclared name: C.SOME_CONST_1
|
||||||
// testdata/errors.go:110: cannot use C.SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)
|
// testdata/errors.go:110: cannot use C.SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)
|
||||||
|
@ -38,29 +38,23 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
const C.SOME_CONST_3 = 1234
|
type (
|
||||||
|
C.char uint8
|
||||||
type C.int16_t = int16
|
C.schar int8
|
||||||
type C.int32_t = int32
|
C.uchar uint8
|
||||||
type C.int64_t = int64
|
C.short int16
|
||||||
type C.int8_t = int8
|
C.ushort uint16
|
||||||
type C.uint16_t = uint16
|
C.int int32
|
||||||
type C.uint32_t = uint32
|
C.uint uint32
|
||||||
type C.uint64_t = uint64
|
C.long int32
|
||||||
type C.uint8_t = uint8
|
C.ulong uint32
|
||||||
type C.uintptr_t = uintptr
|
C.longlong int64
|
||||||
type C.char uint8
|
C.ulonglong uint64
|
||||||
type C.int int32
|
)
|
||||||
type C.long int32
|
type C._Ctype_struct___0 struct {
|
||||||
type C.longlong int64
|
|
||||||
type C.schar int8
|
|
||||||
type C.short int16
|
|
||||||
type C.uchar uint8
|
|
||||||
type C.uint uint32
|
|
||||||
type C.ulong uint32
|
|
||||||
type C.ulonglong uint64
|
|
||||||
type C.ushort uint16
|
|
||||||
type C.point_t = struct {
|
|
||||||
x C.int
|
x C.int
|
||||||
y C.int
|
y C.int
|
||||||
}
|
}
|
||||||
|
type C.point_t = C._Ctype_struct___0
|
||||||
|
|
||||||
|
const C.SOME_CONST_3 = 1234
|
||||||
|
|
35
cgo/testdata/flags.out.go
предоставленный
35
cgo/testdata/flags.out.go
предоставленный
|
@ -29,26 +29,19 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
C.char uint8
|
||||||
|
C.schar int8
|
||||||
|
C.uchar uint8
|
||||||
|
C.short int16
|
||||||
|
C.ushort uint16
|
||||||
|
C.int int32
|
||||||
|
C.uint uint32
|
||||||
|
C.long int32
|
||||||
|
C.ulong uint32
|
||||||
|
C.longlong int64
|
||||||
|
C.ulonglong uint64
|
||||||
|
)
|
||||||
|
|
||||||
const C.BAR = 3
|
const C.BAR = 3
|
||||||
const C.FOO_H = 1
|
const C.FOO_H = 1
|
||||||
|
|
||||||
type C.int16_t = int16
|
|
||||||
type C.int32_t = int32
|
|
||||||
type C.int64_t = int64
|
|
||||||
type C.int8_t = int8
|
|
||||||
type C.uint16_t = uint16
|
|
||||||
type C.uint32_t = uint32
|
|
||||||
type C.uint64_t = uint64
|
|
||||||
type C.uint8_t = uint8
|
|
||||||
type C.uintptr_t = uintptr
|
|
||||||
type C.char uint8
|
|
||||||
type C.int int32
|
|
||||||
type C.long int32
|
|
||||||
type C.longlong int64
|
|
||||||
type C.schar int8
|
|
||||||
type C.short int16
|
|
||||||
type C.uchar uint8
|
|
||||||
type C.uint uint32
|
|
||||||
type C.ulong uint32
|
|
||||||
type C.ulonglong uint64
|
|
||||||
type C.ushort uint16
|
|
||||||
|
|
41
cgo/testdata/symbols.out.go
предоставленный
41
cgo/testdata/symbols.out.go
предоставленный
|
@ -24,41 +24,36 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
C.char uint8
|
||||||
|
C.schar int8
|
||||||
|
C.uchar uint8
|
||||||
|
C.short int16
|
||||||
|
C.ushort uint16
|
||||||
|
C.int int32
|
||||||
|
C.uint uint32
|
||||||
|
C.long int32
|
||||||
|
C.ulong uint32
|
||||||
|
C.longlong int64
|
||||||
|
C.ulonglong uint64
|
||||||
|
)
|
||||||
|
|
||||||
//export foo
|
//export foo
|
||||||
func C.foo(a C.int, b C.int) C.int
|
func C.foo(a C.int, b C.int) C.int
|
||||||
|
|
||||||
|
var C.foo$funcaddr unsafe.Pointer
|
||||||
|
|
||||||
//export variadic0
|
//export variadic0
|
||||||
//go:variadic
|
//go:variadic
|
||||||
func C.variadic0()
|
func C.variadic0()
|
||||||
|
|
||||||
|
var C.variadic0$funcaddr unsafe.Pointer
|
||||||
|
|
||||||
//export variadic2
|
//export variadic2
|
||||||
//go:variadic
|
//go:variadic
|
||||||
func C.variadic2(x C.int, y C.int)
|
func C.variadic2(x C.int, y C.int)
|
||||||
|
|
||||||
var C.foo$funcaddr unsafe.Pointer
|
|
||||||
var C.variadic0$funcaddr unsafe.Pointer
|
|
||||||
var C.variadic2$funcaddr unsafe.Pointer
|
var C.variadic2$funcaddr unsafe.Pointer
|
||||||
|
|
||||||
//go:extern someValue
|
//go:extern someValue
|
||||||
var C.someValue C.int
|
var C.someValue C.int
|
||||||
|
|
||||||
type C.int16_t = int16
|
|
||||||
type C.int32_t = int32
|
|
||||||
type C.int64_t = int64
|
|
||||||
type C.int8_t = int8
|
|
||||||
type C.uint16_t = uint16
|
|
||||||
type C.uint32_t = uint32
|
|
||||||
type C.uint64_t = uint64
|
|
||||||
type C.uint8_t = uint8
|
|
||||||
type C.uintptr_t = uintptr
|
|
||||||
type C.char uint8
|
|
||||||
type C.int int32
|
|
||||||
type C.long int32
|
|
||||||
type C.longlong int64
|
|
||||||
type C.schar int8
|
|
||||||
type C.short int16
|
|
||||||
type C.uchar uint8
|
|
||||||
type C.uint uint32
|
|
||||||
type C.ulong uint32
|
|
||||||
type C.ulonglong uint64
|
|
||||||
type C.ushort uint16
|
|
||||||
|
|
202
cgo/testdata/types.out.go
предоставленный
202
cgo/testdata/types.out.go
предоставленный
|
@ -24,132 +24,126 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
const C.option2A = 20
|
type (
|
||||||
const C.optionA = 0
|
C.char uint8
|
||||||
const C.optionB = 1
|
C.schar int8
|
||||||
const C.optionC = -5
|
C.uchar uint8
|
||||||
const C.optionD = -4
|
C.short int16
|
||||||
const C.optionE = 10
|
C.ushort uint16
|
||||||
const C.optionF = 11
|
C.int int32
|
||||||
const C.optionG = 12
|
C.uint uint32
|
||||||
const C.unused1 = 5
|
C.long int32
|
||||||
|
C.ulong uint32
|
||||||
type C.int16_t = int16
|
C.longlong int64
|
||||||
type C.int32_t = int32
|
C.ulonglong uint64
|
||||||
type C.int64_t = int64
|
)
|
||||||
type C.int8_t = int8
|
|
||||||
type C.uint16_t = uint16
|
|
||||||
type C.uint32_t = uint32
|
|
||||||
type C.uint64_t = uint64
|
|
||||||
type C.uint8_t = uint8
|
|
||||||
type C.uintptr_t = uintptr
|
|
||||||
type C.char uint8
|
|
||||||
type C.int int32
|
|
||||||
type C.long int32
|
|
||||||
type C.longlong int64
|
|
||||||
type C.schar int8
|
|
||||||
type C.short int16
|
|
||||||
type C.uchar uint8
|
|
||||||
type C.uint uint32
|
|
||||||
type C.ulong uint32
|
|
||||||
type C.ulonglong uint64
|
|
||||||
type C.ushort uint16
|
|
||||||
type C.bitfield_t = C.struct_4
|
|
||||||
type C.myIntArray = [10]C.int
|
|
||||||
type C.myint = C.int
|
type C.myint = C.int
|
||||||
type C.option2_t = C.uint
|
type C._Ctype_struct___0 struct {
|
||||||
type C.option_t = C.enum_option
|
|
||||||
type C.point2d_t = struct {
|
|
||||||
x C.int
|
x C.int
|
||||||
y C.int
|
y C.int
|
||||||
}
|
}
|
||||||
type C.point3d_t = C.struct_point3d
|
type C.point2d_t = C._Ctype_struct___0
|
||||||
type C.struct_nested_t = struct {
|
|
||||||
begin C.point2d_t
|
|
||||||
end C.point2d_t
|
|
||||||
tag C.int
|
|
||||||
|
|
||||||
coord C.union_2
|
|
||||||
}
|
|
||||||
type C.types_t = struct {
|
|
||||||
f float32
|
|
||||||
d float64
|
|
||||||
ptr *C.int
|
|
||||||
}
|
|
||||||
type C.union1_t = struct{ i C.int }
|
|
||||||
type C.union2d_t = C.union_union2d
|
|
||||||
type C.union3_t = C.union_1
|
|
||||||
type C.union_nested_t = C.union_3
|
|
||||||
type C.unionarray_t = struct{ arr [10]C.uchar }
|
|
||||||
|
|
||||||
func (s *C.struct_4) bitfield_a() C.uchar { return s.__bitfield_1 & 0x1f }
|
|
||||||
func (s *C.struct_4) set_bitfield_a(value C.uchar) {
|
|
||||||
s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0
|
|
||||||
}
|
|
||||||
func (s *C.struct_4) bitfield_b() C.uchar {
|
|
||||||
return s.__bitfield_1 >> 5 & 0x1
|
|
||||||
}
|
|
||||||
func (s *C.struct_4) set_bitfield_b(value C.uchar) {
|
|
||||||
s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5
|
|
||||||
}
|
|
||||||
func (s *C.struct_4) bitfield_c() C.uchar {
|
|
||||||
return s.__bitfield_1 >> 6
|
|
||||||
}
|
|
||||||
func (s *C.struct_4) set_bitfield_c(value C.uchar,
|
|
||||||
|
|
||||||
) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 }
|
|
||||||
|
|
||||||
type C.struct_4 struct {
|
|
||||||
start C.uchar
|
|
||||||
__bitfield_1 C.uchar
|
|
||||||
|
|
||||||
d C.uchar
|
|
||||||
e C.uchar
|
|
||||||
}
|
|
||||||
type C.struct_point3d struct {
|
type C.struct_point3d struct {
|
||||||
x C.int
|
x C.int
|
||||||
y C.int
|
y C.int
|
||||||
z C.int
|
z C.int
|
||||||
}
|
}
|
||||||
|
type C.point3d_t = C.struct_point3d
|
||||||
type C.struct_type1 struct {
|
type C.struct_type1 struct {
|
||||||
_type C.int
|
_type C.int
|
||||||
__type C.int
|
__type C.int
|
||||||
___type C.int
|
___type C.int
|
||||||
}
|
}
|
||||||
type C.struct_type2 struct{ _type C.int }
|
type C.struct_type2 struct{ _type C.int }
|
||||||
|
type C._Ctype_union___1 struct{ i C.int }
|
||||||
|
type C.union1_t = C._Ctype_union___1
|
||||||
|
type C._Ctype_union___2 struct{ $union uint64 }
|
||||||
|
|
||||||
func (union *C.union_1) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) }
|
func (union *C._Ctype_union___2) unionfield_i() *C.int {
|
||||||
func (union *C.union_1) unionfield_d() *float64 { return (*float64)(unsafe.Pointer(&union.$union)) }
|
return (*C.int)(unsafe.Pointer(&union.$union))
|
||||||
func (union *C.union_1) unionfield_s() *C.short { return (*C.short)(unsafe.Pointer(&union.$union)) }
|
|
||||||
|
|
||||||
type C.union_1 struct{ $union uint64 }
|
|
||||||
|
|
||||||
func (union *C.union_2) unionfield_area() *C.point2d_t {
|
|
||||||
return (*C.point2d_t)(unsafe.Pointer(&union.$union))
|
|
||||||
}
|
}
|
||||||
func (union *C.union_2) unionfield_solid() *C.point3d_t {
|
func (union *C._Ctype_union___2) unionfield_d() *float64 {
|
||||||
return (*C.point3d_t)(unsafe.Pointer(&union.$union))
|
return (*float64)(unsafe.Pointer(&union.$union))
|
||||||
|
}
|
||||||
|
func (union *C._Ctype_union___2) unionfield_s() *C.short {
|
||||||
|
return (*C.short)(unsafe.Pointer(&union.$union))
|
||||||
}
|
}
|
||||||
|
|
||||||
type C.union_2 struct{ $union [3]uint32 }
|
type C.union3_t = C._Ctype_union___2
|
||||||
|
type C.union_union2d struct{ $union [2]uint64 }
|
||||||
func (union *C.union_3) unionfield_point() *C.point3d_t {
|
|
||||||
return (*C.point3d_t)(unsafe.Pointer(&union.$union))
|
|
||||||
}
|
|
||||||
func (union *C.union_3) unionfield_array() *C.unionarray_t {
|
|
||||||
return (*C.unionarray_t)(unsafe.Pointer(&union.$union))
|
|
||||||
}
|
|
||||||
func (union *C.union_3) unionfield_thing() *C.union3_t {
|
|
||||||
return (*C.union3_t)(unsafe.Pointer(&union.$union))
|
|
||||||
}
|
|
||||||
|
|
||||||
type C.union_3 struct{ $union [2]uint64 }
|
|
||||||
|
|
||||||
func (union *C.union_union2d) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) }
|
func (union *C.union_union2d) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) }
|
||||||
func (union *C.union_union2d) unionfield_d() *[2]float64 {
|
func (union *C.union_union2d) unionfield_d() *[2]float64 {
|
||||||
return (*[2]float64)(unsafe.Pointer(&union.$union))
|
return (*[2]float64)(unsafe.Pointer(&union.$union))
|
||||||
}
|
}
|
||||||
|
|
||||||
type C.union_union2d struct{ $union [2]uint64 }
|
type C.union2d_t = C.union_union2d
|
||||||
type C.enum_option C.int
|
type C._Ctype_union___3 struct{ arr [10]C.uchar }
|
||||||
type C.enum_unused C.uint
|
type C.unionarray_t = C._Ctype_union___3
|
||||||
|
type C._Ctype_union___5 struct{ $union [3]uint32 }
|
||||||
|
|
||||||
|
func (union *C._Ctype_union___5) unionfield_area() *C.point2d_t {
|
||||||
|
return (*C.point2d_t)(unsafe.Pointer(&union.$union))
|
||||||
|
}
|
||||||
|
func (union *C._Ctype_union___5) unionfield_solid() *C.point3d_t {
|
||||||
|
return (*C.point3d_t)(unsafe.Pointer(&union.$union))
|
||||||
|
}
|
||||||
|
|
||||||
|
type C._Ctype_struct___4 struct {
|
||||||
|
begin C.point2d_t
|
||||||
|
end C.point2d_t
|
||||||
|
tag C.int
|
||||||
|
|
||||||
|
coord C._Ctype_union___5
|
||||||
|
}
|
||||||
|
type C.struct_nested_t = C._Ctype_struct___4
|
||||||
|
type C._Ctype_union___6 struct{ $union [2]uint64 }
|
||||||
|
|
||||||
|
func (union *C._Ctype_union___6) unionfield_point() *C.point3d_t {
|
||||||
|
return (*C.point3d_t)(unsafe.Pointer(&union.$union))
|
||||||
|
}
|
||||||
|
func (union *C._Ctype_union___6) unionfield_array() *C.unionarray_t {
|
||||||
|
return (*C.unionarray_t)(unsafe.Pointer(&union.$union))
|
||||||
|
}
|
||||||
|
func (union *C._Ctype_union___6) unionfield_thing() *C.union3_t {
|
||||||
|
return (*C.union3_t)(unsafe.Pointer(&union.$union))
|
||||||
|
}
|
||||||
|
|
||||||
|
type C.union_nested_t = C._Ctype_union___6
|
||||||
|
type C.enum_option = C.int
|
||||||
|
type C.option_t = C.enum_option
|
||||||
|
type C._Ctype_enum___7 = C.uint
|
||||||
|
type C.option2_t = C._Ctype_enum___7
|
||||||
|
type C._Ctype_struct___8 struct {
|
||||||
|
f float32
|
||||||
|
d float64
|
||||||
|
ptr *C.int
|
||||||
|
}
|
||||||
|
type C.types_t = C._Ctype_struct___8
|
||||||
|
type C.myIntArray = [10]C.int
|
||||||
|
type C._Ctype_struct___9 struct {
|
||||||
|
start C.uchar
|
||||||
|
__bitfield_1 C.uchar
|
||||||
|
|
||||||
|
d C.uchar
|
||||||
|
e C.uchar
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *C._Ctype_struct___9) bitfield_a() C.uchar { return s.__bitfield_1 & 0x1f }
|
||||||
|
func (s *C._Ctype_struct___9) set_bitfield_a(value C.uchar) {
|
||||||
|
s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0
|
||||||
|
}
|
||||||
|
func (s *C._Ctype_struct___9) bitfield_b() C.uchar {
|
||||||
|
return s.__bitfield_1 >> 5 & 0x1
|
||||||
|
}
|
||||||
|
func (s *C._Ctype_struct___9) set_bitfield_b(value C.uchar) {
|
||||||
|
s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5
|
||||||
|
}
|
||||||
|
func (s *C._Ctype_struct___9) bitfield_c() C.uchar {
|
||||||
|
return s.__bitfield_1 >> 6
|
||||||
|
}
|
||||||
|
func (s *C._Ctype_struct___9) set_bitfield_c(value C.uchar,
|
||||||
|
|
||||||
|
) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 }
|
||||||
|
|
||||||
|
type C.bitfield_t = C._Ctype_struct___9
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче