TestPrintf

This commit is contained in:
xushiwei
2024-04-20 13:50:48 +08:00
parent 6a359a4d4d
commit 1ec438a361
3 changed files with 66 additions and 17 deletions

View File

@@ -105,19 +105,24 @@ type aFunction struct {
Expr Expr
prog Program prog Program
params []Type params []Type
hasVArg bool
} }
type Function = *aFunction type Function = *aFunction
func newFunction(fn llvm.Value, t Type, prog Program) Function { func newFunction(fn llvm.Value, t Type, prog Program) Function {
return &aFunction{Expr{fn, t}, prog, newParams(t, prog)} params, hasVArg := newParams(t, prog)
return &aFunction{Expr{fn, t}, prog, params, hasVArg}
} }
func newParams(fn Type, prog Program) (params []Type) { func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
sig := fn.t.(*types.Signature) sig := fn.t.(*types.Signature)
in := sig.Params() in := sig.Params()
if n := in.Len(); n > 0 { if n := in.Len(); n > 0 {
if hasVArg = HasVArg(in, n); hasVArg {
n--
}
params = make([]Type, n) params = make([]Type, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
params[i] = prog.llvmType(in.At(i).Type()) params[i] = prog.llvmType(in.At(i).Type())

View File

@@ -192,6 +192,21 @@ define { i64, double } @fn(double %0) {
`) `)
} }
func TestPrintf(t *testing.T) {
prog := NewProgram(nil)
pkg := prog.NewPackage("bar", "foo/bar")
pchar := types.NewPointer(types.Typ[types.Int8])
params := types.NewTuple(types.NewVar(0, nil, "format", pchar), VArg())
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int32]))
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
pkg.NewFunc("printf", sig)
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
source_filename = "foo/bar"
declare i32 @printf(ptr, ...)
`)
}
func TestBinOp(t *testing.T) { func TestBinOp(t *testing.T) {
prog := NewProgram(nil) prog := NewProgram(nil)
pkg := prog.NewPackage("bar", "foo/bar") pkg := prog.NewPackage("bar", "foo/bar")

View File

@@ -18,6 +18,7 @@ package ssa
import ( import (
"go/types" "go/types"
"log"
"github.com/goplus/llvm" "github.com/goplus/llvm"
) )
@@ -40,6 +41,24 @@ const (
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
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))
}
// -----------------------------------------------------------------------------
type aType struct { type aType struct {
ll llvm.Type ll llvm.Type
t types.Type t types.Type
@@ -181,6 +200,7 @@ func (p Program) toLLVMType(typ types.Type) Type {
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid} return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
case *types.Chan: case *types.Chan:
} }
log.Println("toLLVMType: todo -", typ)
panic("todo") panic("todo")
} }
@@ -196,30 +216,39 @@ func (p Program) toLLVMStruct(typ *types.Struct) Type {
return &aType{p.ctx.StructType(fields, false), typ, vkInvalid} return &aType{p.ctx.StructType(fields, false), typ, vkInvalid}
} }
func (p Program) toLLVMFields(typ *types.Struct) []llvm.Type { func (p Program) toLLVMFields(typ *types.Struct) (fields []llvm.Type) {
n := typ.NumFields() n := typ.NumFields()
fields := make([]llvm.Type, n) if n > 0 {
for i := 0; i < n; i++ { fields = make([]llvm.Type, n)
fields[i] = p.llvmType(typ.Field(i).Type()).ll for i := 0; i < n; i++ {
fields[i] = p.llvmType(typ.Field(i).Type()).ll
}
} }
return fields return
} }
func (p Program) toLLVMTuple(t *types.Tuple) llvm.Type { func (p Program) toLLVMTuple(t *types.Tuple) llvm.Type {
return p.ctx.StructType(p.toLLVMTypes(t), false) return p.ctx.StructType(p.toLLVMTypes(t, t.Len()), false)
} }
func (p Program) toLLVMTypes(t *types.Tuple) []llvm.Type { func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) {
n := t.Len() if n > 0 {
ret := make([]llvm.Type, n) ret = make([]llvm.Type, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
ret[i] = p.llvmType(t.At(i).Type()).ll ret[i] = p.llvmType(t.At(i).Type()).ll
}
} }
return ret return
} }
func (p Program) toLLVMFunc(sig *types.Signature) Type { func (p Program) toLLVMFunc(sig *types.Signature) Type {
params := p.toLLVMTypes(sig.Params()) tParams := sig.Params()
n := tParams.Len()
hasVArg := HasVArg(tParams, n)
if hasVArg {
n--
}
params := p.toLLVMTypes(tParams, n)
out := sig.Results() out := sig.Results()
var ret llvm.Type var ret llvm.Type
switch nret := out.Len(); nret { switch nret := out.Len(); nret {
@@ -230,7 +259,7 @@ func (p Program) toLLVMFunc(sig *types.Signature) Type {
default: default:
ret = p.toLLVMTuple(out) ret = p.toLLVMTuple(out)
} }
ft := llvm.FunctionType(ret, params, sig.Variadic()) ft := llvm.FunctionType(ret, params, hasVArg)
return &aType{ft, sig, vkFunc} return &aType{ft, sig, vkFunc}
} }