internal/cabi: support arch 386

This commit is contained in:
visualfc
2025-08-19 15:01:35 +08:00
parent 04bb3eb5a9
commit fd0b2ff72d
11 changed files with 294 additions and 77 deletions

View File

@@ -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: