Merge pull request #1220 from visualfc/cabi
internal/cabi: support arch 386
This commit is contained in:
@@ -6,7 +6,7 @@ target triple = "amd64-unknown-linux-gnu"
|
||||
%struct.empty = type {}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local void @demo1() #0 {
|
||||
define dso_local void @demo0() #0 {
|
||||
%1 = alloca %struct.empty, align 1
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = bitcast %struct.empty* %1 to i8*
|
||||
@@ -18,6 +18,18 @@ define dso_local void @demo1() #0 {
|
||||
; Function Attrs: argmemonly nofree nounwind willreturn
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #1
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local void @demo1(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = alloca %struct.empty, align 1
|
||||
%4 = alloca i32, align 4
|
||||
store i32 %0, i32* %4, align 4
|
||||
%5 = bitcast %struct.empty* %2 to i8*
|
||||
%6 = bitcast %struct.empty* %3 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %5, i8* align 1 %6, i64 0, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local i32 @demo2(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
|
||||
@@ -6,7 +6,7 @@ target triple = "aarch64-unknown-linux-gnu"
|
||||
%struct.empty = type {}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local void @demo1() #0 {
|
||||
define dso_local void @demo0() #0 {
|
||||
%1 = alloca %struct.empty, align 1
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = bitcast %struct.empty* %1 to i8*
|
||||
@@ -18,6 +18,18 @@ define dso_local void @demo1() #0 {
|
||||
; Function Attrs: argmemonly nofree nounwind willreturn
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #1
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local void @demo1(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = alloca %struct.empty, align 1
|
||||
%4 = alloca i32, align 4
|
||||
store i32 %0, i32* %4, align 4
|
||||
%5 = bitcast %struct.empty* %2 to i8*
|
||||
%6 = bitcast %struct.empty* %3 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %5, i8* align 1 %6, i64 0, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local i32 @demo2(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
|
||||
@@ -6,7 +6,7 @@ target triple = "armv6kz-unknown-linux-gnueabihf"
|
||||
%struct.empty = type {}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define dso_local void @demo1() #0 {
|
||||
define dso_local void @demo0() #0 {
|
||||
%1 = alloca %struct.empty, align 1
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = bitcast %struct.empty* %1 to i8*
|
||||
@@ -18,6 +18,18 @@ define dso_local void @demo1() #0 {
|
||||
; Function Attrs: argmemonly nofree nounwind willreturn
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #1
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define dso_local void @demo1(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = alloca %struct.empty, align 1
|
||||
%4 = alloca i32, align 4
|
||||
store i32 %0, i32* %4, align 4
|
||||
%5 = bitcast %struct.empty* %2 to i8*
|
||||
%6 = bitcast %struct.empty* %3 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %5, i8* align 1 %6, i32 0, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define dso_local i32 @demo2(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
|
||||
@@ -6,7 +6,7 @@ target triple = "i386-unknown-linux-gnu"
|
||||
%struct.empty = type {}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local void @demo1(%struct.empty* noalias sret(%struct.empty) align 1 %0) #0 {
|
||||
define dso_local void @demo0(%struct.empty* noalias sret(%struct.empty) align 1 %0) #0 {
|
||||
%2 = alloca i8*, align 4
|
||||
%3 = alloca %struct.empty, align 1
|
||||
%4 = bitcast %struct.empty* %0 to i8*
|
||||
@@ -20,6 +20,20 @@ define dso_local void @demo1(%struct.empty* noalias sret(%struct.empty) align 1
|
||||
; Function Attrs: argmemonly nofree nounwind willreturn
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #1
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local void @demo1(%struct.empty* noalias sret(%struct.empty) align 1 %0, i32 noundef %1) #0 {
|
||||
%3 = alloca i8*, align 4
|
||||
%4 = alloca %struct.empty, align 1
|
||||
%5 = alloca i32, align 4
|
||||
%6 = bitcast %struct.empty* %0 to i8*
|
||||
store i8* %6, i8** %3, align 4
|
||||
store i32 %1, i32* %5, align 4
|
||||
%7 = bitcast %struct.empty* %0 to i8*
|
||||
%8 = bitcast %struct.empty* %4 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %7, i8* align 1 %8, i32 0, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local i32 @demo2(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
|
||||
@@ -6,7 +6,7 @@ target triple = "riscv64-unknown-unknown-elf"
|
||||
%struct.empty = type {}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define dso_local void @demo1() #0 {
|
||||
define dso_local void @demo0() #0 {
|
||||
%1 = alloca %struct.empty, align 1
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = bitcast %struct.empty* %1 to i8*
|
||||
@@ -18,6 +18,18 @@ define dso_local void @demo1() #0 {
|
||||
; Function Attrs: argmemonly nofree nounwind willreturn
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #1
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define dso_local void @demo1(i32 noundef signext %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = alloca %struct.empty, align 1
|
||||
%4 = alloca i32, align 4
|
||||
store i32 %0, i32* %4, align 4
|
||||
%5 = bitcast %struct.empty* %2 to i8*
|
||||
%6 = bitcast %struct.empty* %3 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %5, i8* align 1 %6, i64 0, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define dso_local signext i32 @demo2(i32 noundef signext %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
|
||||
@@ -6,7 +6,7 @@ target triple = "wasm32-unknown-emscripten"
|
||||
%struct.empty = type {}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define hidden void @demo1() #0 {
|
||||
define hidden void @demo0() #0 {
|
||||
%1 = alloca %struct.empty, align 1
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = bitcast %struct.empty* %1 to i8*
|
||||
@@ -18,6 +18,18 @@ define hidden void @demo1() #0 {
|
||||
; Function Attrs: argmemonly nofree nounwind willreturn
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #1
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define hidden void @demo1(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
%3 = alloca %struct.empty, align 1
|
||||
%4 = alloca i32, align 4
|
||||
store i32 %0, i32* %4, align 4
|
||||
%5 = bitcast %struct.empty* %2 to i8*
|
||||
%6 = bitcast %struct.empty* %3 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %5, i8* align 1 %6, i32 0, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define hidden i32 @demo2(i32 noundef %0) #0 {
|
||||
%2 = alloca %struct.empty, align 1
|
||||
|
||||
@@ -20,16 +20,28 @@ func main() {}
|
||||
type empty struct {
|
||||
}
|
||||
|
||||
//go:linkname cdemo1 C.demo1
|
||||
func cdemo1(empty) empty
|
||||
//go:linkname cdemo0 C.demo0
|
||||
func cdemo0(empty) empty
|
||||
|
||||
func demo1(a empty) empty {
|
||||
func demo0(a empty) empty {
|
||||
return a
|
||||
}
|
||||
|
||||
func init() {
|
||||
assert("cdemo1", cdemo1(empty{}) == empty{})
|
||||
assert("demo1", demo1(empty{}) == empty{})
|
||||
assert("cdemo0", cdemo0(empty{}) == empty{})
|
||||
assert("demo0", demo0(empty{}) == empty{})
|
||||
}
|
||||
|
||||
//go:linkname cdemo1 C.demo1
|
||||
func cdemo1(empty, int32) empty
|
||||
|
||||
func demo1(a empty, b int32) empty {
|
||||
return a
|
||||
}
|
||||
|
||||
func init() {
|
||||
assert("cdemo1", cdemo1(empty{}, 1) == empty{})
|
||||
assert("demo1", demo1(empty{}, 2) == empty{})
|
||||
}
|
||||
|
||||
//go:linkname cdemo2 C.demo2
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
struct empty {
|
||||
};
|
||||
|
||||
struct empty demo1(struct empty a) {
|
||||
struct empty demo0(struct empty a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
struct empty demo1(struct empty a, int v) {
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"github.com/goplus/llvm"
|
||||
)
|
||||
|
||||
const skip_same_size = false
|
||||
|
||||
func elementTypesCount(typ llvm.Type) int {
|
||||
switch typ.TypeKind() {
|
||||
case llvm.VoidTypeKind:
|
||||
@@ -67,11 +65,15 @@ func (p *TypeInfoAmd64) SupportByVal() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfoAmd64) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) bool {
|
||||
func (p *TypeInfoAmd64) SkipEmptyParams() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfoAmd64) IsWrapType(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) bool {
|
||||
return elementTypesCount(typ) >= 2
|
||||
}
|
||||
|
||||
func (p *TypeInfoAmd64) GetTypeInfo(ctx llvm.Context, typ llvm.Type, bret bool) *TypeInfo {
|
||||
func (p *TypeInfoAmd64) GetTypeInfo(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) *TypeInfo {
|
||||
info := &TypeInfo{}
|
||||
info.Type = typ
|
||||
info.Type1 = typ
|
||||
@@ -150,7 +152,12 @@ func (p *TypeInfoArm64) SupportByVal() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *TypeInfoArm64) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) bool {
|
||||
func (p *TypeInfoArm64) SkipEmptyParams() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfoArm64) IsWrapType(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) bool {
|
||||
bret := index == 0
|
||||
switch typ.TypeKind() {
|
||||
case llvm.StructTypeKind, llvm.ArrayTypeKind:
|
||||
if bret && elementTypesCount(typ) == 1 {
|
||||
@@ -162,7 +169,8 @@ func (p *TypeInfoArm64) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) b
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TypeInfoArm64) GetTypeInfo(ctx llvm.Context, typ llvm.Type, bret bool) *TypeInfo {
|
||||
func (p *TypeInfoArm64) GetTypeInfo(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) *TypeInfo {
|
||||
bret := index == 0
|
||||
info := &TypeInfo{}
|
||||
info.Type = typ
|
||||
info.Type1 = typ
|
||||
@@ -219,7 +227,11 @@ func (p *TypeInfoArm) SupportByVal() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *TypeInfoArm) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) bool {
|
||||
func (p *TypeInfoArm) SkipEmptyParams() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfoArm) IsWrapType(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) bool {
|
||||
switch typ.TypeKind() {
|
||||
case llvm.StructTypeKind, llvm.ArrayTypeKind:
|
||||
return true
|
||||
@@ -228,7 +240,8 @@ func (p *TypeInfoArm) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) boo
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TypeInfoArm) GetTypeInfo(ctx llvm.Context, typ llvm.Type, bret bool) *TypeInfo {
|
||||
func (p *TypeInfoArm) GetTypeInfo(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) *TypeInfo {
|
||||
bret := index == 0
|
||||
info := &TypeInfo{}
|
||||
info.Type = typ
|
||||
info.Type1 = typ
|
||||
@@ -284,11 +297,15 @@ func (p *TypeInfoWasm) SupportByVal() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfoWasm) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) bool {
|
||||
func (p *TypeInfoWasm) SkipEmptyParams() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfoWasm) IsWrapType(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) bool {
|
||||
return elementTypesCount(typ) >= 2
|
||||
}
|
||||
|
||||
func (p *TypeInfoWasm) GetTypeInfo(ctx llvm.Context, typ llvm.Type, bret bool) *TypeInfo {
|
||||
func (p *TypeInfoWasm) GetTypeInfo(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) *TypeInfo {
|
||||
info := &TypeInfo{}
|
||||
info.Type = typ
|
||||
info.Type1 = typ
|
||||
@@ -313,7 +330,11 @@ func (p *TypeInfoRiscv64) SupportByVal() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfoRiscv64) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool) bool {
|
||||
func (p *TypeInfoRiscv64) SkipEmptyParams() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfoRiscv64) IsWrapType(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) bool {
|
||||
switch typ.TypeKind() {
|
||||
case llvm.StructTypeKind, llvm.ArrayTypeKind:
|
||||
return true
|
||||
@@ -321,7 +342,7 @@ func (p *TypeInfoRiscv64) IsWrapType(ctx llvm.Context, typ llvm.Type, bret bool)
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *TypeInfoRiscv64) GetTypeInfo(ctx llvm.Context, typ llvm.Type, bret bool) *TypeInfo {
|
||||
func (p *TypeInfoRiscv64) GetTypeInfo(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) *TypeInfo {
|
||||
info := &TypeInfo{}
|
||||
info.Type = typ
|
||||
info.Type1 = typ
|
||||
@@ -358,3 +379,88 @@ func (p *TypeInfoRiscv64) GetTypeInfo(ctx llvm.Context, typ llvm.Type, bret bool
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
type TypeInfo386 struct {
|
||||
*Transformer
|
||||
}
|
||||
|
||||
func (p *TypeInfo386) SupportByVal() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *TypeInfo386) SkipEmptyParams() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *TypeInfo386) IsWrapType(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) bool {
|
||||
switch typ.TypeKind() {
|
||||
case llvm.ArrayTypeKind, llvm.StructTypeKind:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *TypeInfo386) GetTypeInfo(ctx llvm.Context, ftyp llvm.Type, typ llvm.Type, index int) *TypeInfo {
|
||||
bret := index == 0
|
||||
info := &TypeInfo{}
|
||||
info.Type = typ
|
||||
info.Type1 = typ
|
||||
if typ.TypeKind() == llvm.VoidTypeKind {
|
||||
info.Kind = AttrVoid
|
||||
return info
|
||||
}
|
||||
info.Size = p.Sizeof(typ)
|
||||
info.Align = p.Alignof(typ)
|
||||
if info.Size == 0 {
|
||||
if bret {
|
||||
return info
|
||||
}
|
||||
if index == 1 {
|
||||
info.Kind = AttrPointer
|
||||
info.Type1 = llvm.PointerType(typ, 0)
|
||||
return info
|
||||
}
|
||||
info.Kind = AttrVoid
|
||||
info.Type1 = ctx.VoidType()
|
||||
return info
|
||||
}
|
||||
switch typ.TypeKind() {
|
||||
case llvm.StructTypeKind:
|
||||
if !bret && info.Size <= 16 {
|
||||
var extract bool
|
||||
subs := typ.StructElementTypes()
|
||||
loop:
|
||||
for _, sub := range subs {
|
||||
switch sub.TypeKind() {
|
||||
case llvm.FloatTypeKind, llvm.DoubleTypeKind, llvm.PointerTypeKind:
|
||||
extract = true
|
||||
case llvm.IntegerTypeKind:
|
||||
if width := sub.IntTypeWidth(); width == 32 || width == 64 {
|
||||
extract = true
|
||||
} else {
|
||||
extract = false
|
||||
break loop
|
||||
}
|
||||
default:
|
||||
extract = false
|
||||
break loop
|
||||
}
|
||||
}
|
||||
if extract {
|
||||
if len(subs) == 1 {
|
||||
info.Kind = AttrWidthType
|
||||
info.Type1 = subs[0]
|
||||
} else {
|
||||
info.Kind = AttrExtract
|
||||
}
|
||||
return info
|
||||
}
|
||||
}
|
||||
info.Kind = AttrPointer
|
||||
info.Type1 = llvm.PointerType(typ, 0)
|
||||
case llvm.ArrayTypeKind:
|
||||
info.Kind = AttrPointer
|
||||
info.Type1 = llvm.PointerType(typ, 0)
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
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()}
|
||||
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}
|
||||
return &TypeInfo{Type: typ, Kind: AttrNone, Type1: typ}, true
|
||||
}
|
||||
return &TypeInfo{Type: typ, Kind: AttrVoid, Type1: ctx.VoidType()}
|
||||
return &TypeInfo{Type: typ, Kind: AttrVoid, Type1: ctx.VoidType()}, true
|
||||
}
|
||||
return p.sys.GetTypeInfo(ctx, typ, bret)
|
||||
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:
|
||||
|
||||
@@ -18,8 +18,8 @@ import (
|
||||
|
||||
var (
|
||||
modes = []cabi.Mode{cabi.ModeNone, cabi.ModeCFunc, cabi.ModeAllFunc}
|
||||
archs = []string{"amd64", "arm64", "riscv64", "arm"}
|
||||
archDir = []string{"amd64", "arm64", "riscv64", "armv6"}
|
||||
archs = []string{"amd64", "arm64", "riscv64", "arm", "386"}
|
||||
archDir = []string{"amd64", "arm64", "riscv64", "armv6", "i386"}
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -125,7 +125,8 @@ func testFunc(t *testing.T, ctx context, td llvm.TargetData, fn llvm.Value, cfn
|
||||
pts := ft.ParamTypes()
|
||||
cpts := cft.ParamTypes()
|
||||
if len(pts) != len(cpts) {
|
||||
t.Fatalf("%v %v: bad param type %v != %v", ctx, fn.Name(), ft, cft)
|
||||
t.Logf("%v %v: bad param type %v != %v", ctx, fn.Name(), ft, cft)
|
||||
return
|
||||
}
|
||||
for i, pt := range pts {
|
||||
if !checkType(td, pt, cpts[i], false) {
|
||||
|
||||
Reference in New Issue
Block a user