llgo/ssa: CType, CFuncDecl
This commit is contained in:
45
ssa/type.go
45
ssa/type.go
@@ -48,27 +48,8 @@ const (
|
|||||||
vkPhisExpr = -2
|
vkPhisExpr = -2
|
||||||
)
|
)
|
||||||
|
|
||||||
// CFuncPtr represents a C function pointer.
|
|
||||||
type CFuncPtr types.Signature
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
const (
|
|
||||||
NameValist = "__llgo_va_list"
|
|
||||||
)
|
|
||||||
|
|
||||||
func VArg() *types.Var {
|
|
||||||
return types.NewParam(0, nil, NameValist, types.Typ[types.Invalid])
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsVArg(arg *types.Var) bool {
|
|
||||||
return arg.Name() == NameValist
|
|
||||||
}
|
|
||||||
|
|
||||||
func HasVArg(t *types.Tuple, n int) bool {
|
|
||||||
return n > 0 && IsVArg(t.At(n-1))
|
|
||||||
}
|
|
||||||
|
|
||||||
func indexType(t types.Type) types.Type {
|
func indexType(t types.Type) types.Type {
|
||||||
switch t := t.(type) {
|
switch t := t.(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
@@ -102,18 +83,6 @@ func methodToFunc(sig *types.Signature) *types.Signature {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// CType convert a C type into Go.
|
|
||||||
func CType(typ types.Type) types.Type {
|
|
||||||
panic("todo")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CFuncDecl convert a C function decl into Go signature.
|
|
||||||
func CFuncDecl(sig *types.Signature) *types.Signature {
|
|
||||||
panic("todo")
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
type aType struct {
|
type aType struct {
|
||||||
ll llvm.Type
|
ll llvm.Type
|
||||||
t types.Type
|
t types.Type
|
||||||
@@ -278,6 +247,8 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
|||||||
return p.toLLVMNamed(t)
|
return p.toLLVMNamed(t)
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
return p.toLLVMFunc(t, false, false)
|
return p.toLLVMFunc(t, false, false)
|
||||||
|
case *CFuncPtr:
|
||||||
|
return p.toLLVMFunc((*types.Signature)(t), true, false)
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elem := p.Type(t.Elem())
|
elem := p.Type(t.Elem())
|
||||||
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
||||||
@@ -327,15 +298,12 @@ func (p Program) toLLVMFunc(sig *types.Signature, inC, isDecl bool) Type {
|
|||||||
var kind valueKind
|
var kind valueKind
|
||||||
var ft llvm.Type
|
var ft llvm.Type
|
||||||
if isDecl || inC {
|
if isDecl || inC {
|
||||||
var tParams = sig.Params()
|
tParams := sig.Params()
|
||||||
var n = tParams.Len()
|
n := tParams.Len()
|
||||||
var hasVArg bool
|
hasVArg := HasVArg(tParams, n)
|
||||||
if inC {
|
|
||||||
hasVArg = HasVArg(tParams, n)
|
|
||||||
if hasVArg {
|
if hasVArg {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
}
|
|
||||||
params := p.toLLVMTypes(tParams, n)
|
params := p.toLLVMTypes(tParams, n)
|
||||||
out := sig.Results()
|
out := sig.Results()
|
||||||
var ret llvm.Type
|
var ret llvm.Type
|
||||||
@@ -378,9 +346,6 @@ func (p Program) toLLVMNamed(typ *types.Named) Type {
|
|||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
name := NameOf(typ)
|
name := NameOf(typ)
|
||||||
return &aType{p.toLLVMNamedStruct(name, t), typ, vkInvalid}
|
return &aType{p.toLLVMNamedStruct(name, t), typ, vkInvalid}
|
||||||
case *types.Signature:
|
|
||||||
inC := true // TODO(xsw): how to check in C
|
|
||||||
return p.toLLVMFunc(t, inC, false)
|
|
||||||
default:
|
default:
|
||||||
return p.Type(t)
|
return p.Type(t)
|
||||||
}
|
}
|
||||||
|
|||||||
128
ssa/type_c.go
Normal file
128
ssa/type_c.go
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ssa
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
NameValist = "__llgo_va_list"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VArg() *types.Var {
|
||||||
|
return types.NewParam(0, nil, NameValist, types.Typ[types.Invalid])
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsVArg(arg *types.Var) bool {
|
||||||
|
return arg.Name() == NameValist
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasVArg(t *types.Tuple, n int) bool {
|
||||||
|
return n > 0 && IsVArg(t.At(n-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// CFuncPtr represents a C function pointer.
|
||||||
|
type CFuncPtr types.Signature
|
||||||
|
|
||||||
|
func (t *CFuncPtr) String() string { return (*types.Signature)(t).String() }
|
||||||
|
func (t *CFuncPtr) Underlying() types.Type { return (*types.Signature)(t) }
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// CType convert a C type into Go.
|
||||||
|
func CType(typ types.Type) types.Type {
|
||||||
|
t, _ := cvtCType(typ)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// CFuncDecl convert a C function decl into Go signature.
|
||||||
|
func CFuncDecl(sig *types.Signature) *types.Signature {
|
||||||
|
hasVArg := sig.Variadic()
|
||||||
|
params, cvt1 := cvtTuple(sig.Params(), hasVArg)
|
||||||
|
results, cvt2 := cvtTuple(sig.Results(), false)
|
||||||
|
if cvt1 || cvt2 {
|
||||||
|
return types.NewSignatureType(nil, nil, nil, params, results, hasVArg)
|
||||||
|
}
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvtCType(typ types.Type) (types.Type, bool) {
|
||||||
|
switch t := typ.(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
case *types.Pointer:
|
||||||
|
if elem, cvt := cvtCType(t.Elem()); cvt {
|
||||||
|
return types.NewPointer(elem), true
|
||||||
|
}
|
||||||
|
case *types.Struct:
|
||||||
|
return cvtCStruct(t)
|
||||||
|
case *types.Signature:
|
||||||
|
t = CFuncDecl(t)
|
||||||
|
return (*CFuncPtr)(t), true
|
||||||
|
case *types.Array:
|
||||||
|
if elem, cvt := cvtCType(t.Elem()); cvt {
|
||||||
|
return types.NewArray(elem, t.Len()), true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
return typ, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvtTuple(t *types.Tuple, hasVArg bool) (*types.Tuple, bool) {
|
||||||
|
n := t.Len()
|
||||||
|
vars := make([]*types.Var, n)
|
||||||
|
needcvt := false
|
||||||
|
if hasVArg {
|
||||||
|
n--
|
||||||
|
vars[n] = t.At(n)
|
||||||
|
}
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
v := t.At(i)
|
||||||
|
if t, cvt := cvtCType(v.Type()); cvt {
|
||||||
|
v = types.NewParam(v.Pos(), v.Pkg(), v.Name(), t)
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
vars[i] = v
|
||||||
|
}
|
||||||
|
if needcvt {
|
||||||
|
return types.NewTuple(vars...), true
|
||||||
|
}
|
||||||
|
return t, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvtCStruct(typ *types.Struct) (*types.Struct, bool) {
|
||||||
|
n := typ.NumFields()
|
||||||
|
flds := make([]*types.Var, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
f := typ.Field(i)
|
||||||
|
if t, cvt := cvtCType(f.Type()); cvt {
|
||||||
|
f = types.NewField(f.Pos(), f.Pkg(), f.Name(), t, f.Anonymous())
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
flds[i] = f
|
||||||
|
}
|
||||||
|
if needcvt {
|
||||||
|
return types.NewStruct(flds, nil), true
|
||||||
|
}
|
||||||
|
return typ, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
Reference in New Issue
Block a user