internal/cabi: support arch 386
This commit is contained in:
@@ -35,6 +35,8 @@ func NewTransformer(prog ssa.Program, mode Mode) *Transformer {
|
||||
tr.sys = &TypeInfoWasm{tr}
|
||||
case "riscv64":
|
||||
tr.sys = &TypeInfoRiscv64{tr}
|
||||
case "386":
|
||||
tr.sys = &TypeInfo386{tr}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
@@ -108,11 +110,11 @@ func (p *Transformer) TransformModule(path string, m llvm.Module) {
|
||||
}
|
||||
|
||||
func (p *Transformer) isWrapFunctionType(ctx llvm.Context, ft llvm.Type) bool {
|
||||
if p.IsWrapType(ctx, ft.ReturnType(), true) {
|
||||
if p.IsWrapType(ctx, ft, ft.ReturnType(), 0) {
|
||||
return true
|
||||
}
|
||||
for _, typ := range ft.ParamTypes() {
|
||||
if p.IsWrapType(ctx, typ, false) {
|
||||
for i, typ := range ft.ParamTypes() {
|
||||
if p.IsWrapType(ctx, ft, typ, i+1) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -121,8 +123,9 @@ func (p *Transformer) isWrapFunctionType(ctx llvm.Context, ft llvm.Type) bool {
|
||||
|
||||
type TypeInfoSys interface {
|
||||
SupportByVal() bool
|
||||
IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) bool
|
||||
GetTypeInfo(ctx llvm.Context, typ llvm.Type, bret bool) *TypeInfo
|
||||
SkipEmptyParams() bool
|
||||
IsWrapType(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) bool
|
||||
GetTypeInfo(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) *TypeInfo
|
||||
}
|
||||
|
||||
type AttrKind int
|
||||
@@ -133,6 +136,7 @@ const (
|
||||
AttrPointer // type => type*
|
||||
AttrWidthType // type => width int i16/i24/i32/i40/i48/i56/i64 float/double
|
||||
AttrWidthType2 // type => width two int {i64,i16} float/double
|
||||
AttrExtract // extract struct type
|
||||
)
|
||||
|
||||
type FuncInfo struct {
|
||||
@@ -176,27 +180,45 @@ func funcInlineHint(ctx llvm.Context) llvm.Attribute {
|
||||
return ctx.CreateEnumAttribute(llvm.AttributeKindID("inlinehint"), 0)
|
||||
}
|
||||
|
||||
func (p *Transformer) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) bool {
|
||||
func (p *Transformer) IsWrapType(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) bool {
|
||||
if p.sys != nil {
|
||||
if !bret && (typ.TypeKind() == llvm.VoidTypeKind || p.Sizeof(typ) == 0) {
|
||||
bret := index == 0
|
||||
if p.sys.SkipEmptyParams() && p.isWrapEmptyType(ctx, typ, bret) {
|
||||
return true
|
||||
}
|
||||
return p.sys.IsWrapType(ctx, typ, bret)
|
||||
return p.sys.IsWrapType(ctx, ftyp, typ, index)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Transformer) GetTypeInfo(ctx llvm.Context, typ llvm.Type, bret bool) *TypeInfo {
|
||||
if p.sys != nil {
|
||||
if typ.TypeKind() == llvm.VoidTypeKind {
|
||||
return &TypeInfo{Type: typ, Kind: AttrVoid, Type1: ctx.VoidType()}
|
||||
} else if p.Sizeof(typ) == 0 {
|
||||
if bret {
|
||||
return &TypeInfo{Type: typ, Kind: AttrNone, Type1: typ}
|
||||
}
|
||||
return &TypeInfo{Type: typ, Kind: AttrVoid, Type1: ctx.VoidType()}
|
||||
func (p *Transformer) isWrapEmptyType(ctx llvm.Context, typ llvm.Type, bret bool) bool {
|
||||
if !bret && (typ.TypeKind() == llvm.VoidTypeKind || p.Sizeof(typ) == 0) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Transformer) getEmptyType(ctx llvm.Context, typ llvm.Type, bret bool) (*TypeInfo, bool) {
|
||||
if typ.TypeKind() == llvm.VoidTypeKind {
|
||||
return &TypeInfo{Type: typ, Kind: AttrVoid, Type1: ctx.VoidType()}, true
|
||||
} else if p.Sizeof(typ) == 0 {
|
||||
if bret {
|
||||
return &TypeInfo{Type: typ, Kind: AttrNone, Type1: typ}, true
|
||||
}
|
||||
return p.sys.GetTypeInfo(ctx, typ, bret)
|
||||
return &TypeInfo{Type: typ, Kind: AttrVoid, Type1: ctx.VoidType()}, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (p *Transformer) GetTypeInfo(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) *TypeInfo {
|
||||
if p.sys != nil {
|
||||
bret := index == 0
|
||||
if p.sys.SkipEmptyParams() {
|
||||
if info, ok := p.getEmptyType(ctx, typ, bret); ok {
|
||||
return info
|
||||
}
|
||||
}
|
||||
return p.sys.GetTypeInfo(ctx, ftyp, typ, index)
|
||||
}
|
||||
panic("not implment: " + p.GOARCH)
|
||||
}
|
||||
@@ -211,11 +233,11 @@ func (p *Transformer) Alignof(typ llvm.Type) int {
|
||||
|
||||
func (p *Transformer) GetFuncInfo(ctx llvm.Context, typ llvm.Type) (info FuncInfo) {
|
||||
info.Type = typ
|
||||
info.Return = p.GetTypeInfo(ctx, typ.ReturnType(), true)
|
||||
info.Return = p.GetTypeInfo(ctx, typ, typ.ReturnType(), 0)
|
||||
params := typ.ParamTypes()
|
||||
info.Params = make([]*TypeInfo, len(params))
|
||||
for i, t := range params {
|
||||
info.Params[i] = p.GetTypeInfo(ctx, t, false)
|
||||
info.Params[i] = p.GetTypeInfo(ctx, typ, t, i+1)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -250,6 +272,9 @@ func (p *Transformer) transformFuncType(ctx llvm.Context, info *FuncInfo) (llvm.
|
||||
}
|
||||
case AttrWidthType2:
|
||||
paramTypes = append(paramTypes, ti.Type1, ti.Type2)
|
||||
case AttrExtract:
|
||||
subs := ti.Type.StructElementTypes()
|
||||
paramTypes = append(paramTypes, subs...)
|
||||
}
|
||||
}
|
||||
return llvm.FunctionType(returnType, paramTypes, info.Type.IsFunctionVarArg()), attrs
|
||||
@@ -331,6 +356,15 @@ func (p *Transformer) transformFuncBody(ctx llvm.Context, info *FuncInfo, fn llv
|
||||
b.CreateStore(params[index], b.CreateStructGEP(typ, iptr, 1, ""))
|
||||
ptr := b.CreateBitCast(iptr, llvm.PointerType(ti.Type, 0), "")
|
||||
nv = b.CreateLoad(ti.Type, ptr, "")
|
||||
case AttrExtract:
|
||||
nsubs := ti.Type.StructElementTypesCount()
|
||||
nv = llvm.Undef(ti.Type)
|
||||
for i := 0; i < nsubs; i++ {
|
||||
nv = b.CreateInsertValue(nv, params[index], i, "")
|
||||
index++
|
||||
}
|
||||
fn.Param(i).ReplaceAllUsesWith(nv)
|
||||
continue
|
||||
}
|
||||
fn.Param(i).ReplaceAllUsesWith(nv)
|
||||
index++
|
||||
@@ -403,6 +437,11 @@ func (p *Transformer) transformCallInstr(ctx llvm.Context, call llvm.Value) bool
|
||||
iptr := b.CreateBitCast(ptr, llvm.PointerType(typ, 0), "")
|
||||
nparams = append(nparams, b.CreateLoad(ti.Type1, b.CreateStructGEP(typ, iptr, 0, ""), ""))
|
||||
nparams = append(nparams, b.CreateLoad(ti.Type2, b.CreateStructGEP(typ, iptr, 1, ""), ""))
|
||||
case AttrExtract:
|
||||
nsubs := ti.Type.StructElementTypesCount()
|
||||
for i := 0; i < nsubs; i++ {
|
||||
nparams = append(nparams, b.CreateExtractValue(param, i, ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,44 +507,15 @@ func (p *Transformer) transformFuncCall(m llvm.Module, fn llvm.Value) {
|
||||
}
|
||||
|
||||
func (p *Transformer) transformCallbackFunc(m llvm.Module, fn llvm.Value) (wrap llvm.Value, ok bool) {
|
||||
var paramTypes []llvm.Type
|
||||
var returnType llvm.Type
|
||||
attrs := make(map[int]llvm.Attribute)
|
||||
ctx := m.Context()
|
||||
info := p.GetFuncInfo(ctx, fn.GlobalValueType())
|
||||
if !info.HasWrap() {
|
||||
return fn, false
|
||||
}
|
||||
|
||||
switch info.Return.Kind {
|
||||
case AttrPointer:
|
||||
returnType = ctx.VoidType()
|
||||
paramTypes = append(paramTypes, info.Return.Type1)
|
||||
attrs[1] = sretAttribute(ctx, info.Return.Type)
|
||||
case AttrWidthType:
|
||||
returnType = info.Return.Type1
|
||||
case AttrWidthType2:
|
||||
returnType = llvm.StructType([]llvm.Type{info.Return.Type1, info.Return.Type2}, false)
|
||||
default:
|
||||
returnType = info.Return.Type1
|
||||
}
|
||||
|
||||
for _, ti := range info.Params {
|
||||
switch ti.Kind {
|
||||
case AttrNone, AttrWidthType:
|
||||
paramTypes = append(paramTypes, ti.Type1)
|
||||
case AttrPointer:
|
||||
paramTypes = append(paramTypes, ti.Type1)
|
||||
if p.sys.SupportByVal() {
|
||||
attrs[len(paramTypes)] = byvalAttribute(ctx, ti.Type)
|
||||
}
|
||||
case AttrWidthType2:
|
||||
paramTypes = append(paramTypes, ti.Type1, ti.Type2)
|
||||
}
|
||||
}
|
||||
nft, attrs := p.transformFuncType(ctx, &info)
|
||||
|
||||
fname := fn.Name()
|
||||
nft := llvm.FunctionType(returnType, paramTypes, info.Type.IsFunctionVarArg())
|
||||
wrapName := "__llgo_cdecl$" + fname
|
||||
if wrapFunc := m.NamedFunction(wrapName); !wrapFunc.IsNil() {
|
||||
return wrapFunc, true
|
||||
@@ -548,6 +558,15 @@ func (p *Transformer) transformCallbackFunc(m llvm.Module, fn llvm.Value) (wrap
|
||||
b.CreateStore(params[index], b.CreateStructGEP(typ, iptr, 1, ""))
|
||||
ptr := b.CreateBitCast(iptr, llvm.PointerType(ti.Type, 0), "")
|
||||
nparams = append(nparams, b.CreateLoad(ti.Type, ptr, ""))
|
||||
case AttrExtract:
|
||||
nsubs := ti.Type.StructElementTypesCount()
|
||||
nv := llvm.Undef(ti.Type)
|
||||
for i := 0; i < nsubs; i++ {
|
||||
nv = b.CreateInsertValue(nv, params[index], i, "")
|
||||
index++
|
||||
}
|
||||
nparams = append(nparams, nv)
|
||||
continue
|
||||
}
|
||||
index++
|
||||
}
|
||||
@@ -564,6 +583,7 @@ func (p *Transformer) transformCallbackFunc(m llvm.Module, fn llvm.Value) (wrap
|
||||
ret := llvm.CreateCall(b, info.Type, fn, nparams)
|
||||
ptr := llvm.CreateAlloca(b, info.Return.Type)
|
||||
b.CreateStore(ret, ptr)
|
||||
returnType := nft.ReturnType()
|
||||
iptr := b.CreateBitCast(ptr, llvm.PointerType(returnType, 0), "")
|
||||
b.CreateRet(b.CreateLoad(returnType, iptr, ""))
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user