11
ssa/decl.go
11
ssa/decl.go
@@ -105,19 +105,24 @@ type aFunction struct {
|
||||
Expr
|
||||
prog Program
|
||||
|
||||
params []Type
|
||||
params []Type
|
||||
hasVArg bool
|
||||
}
|
||||
|
||||
type Function = *aFunction
|
||||
|
||||
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)
|
||||
in := sig.Params()
|
||||
if n := in.Len(); n > 0 {
|
||||
if hasVArg = HasVArg(in, n); hasVArg {
|
||||
n--
|
||||
}
|
||||
params = make([]Type, n)
|
||||
for i := 0; i < n; i++ {
|
||||
params[i] = prog.llvmType(in.At(i).Type())
|
||||
|
||||
@@ -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) {
|
||||
prog := NewProgram(nil)
|
||||
pkg := prog.NewPackage("bar", "foo/bar")
|
||||
|
||||
57
ssa/type.go
57
ssa/type.go
@@ -18,6 +18,7 @@ package ssa
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"log"
|
||||
|
||||
"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 {
|
||||
ll llvm.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}
|
||||
case *types.Chan:
|
||||
}
|
||||
log.Println("toLLVMType: todo -", typ)
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
@@ -196,30 +216,39 @@ func (p Program) toLLVMStruct(typ *types.Struct) Type {
|
||||
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()
|
||||
fields := make([]llvm.Type, n)
|
||||
for i := 0; i < n; i++ {
|
||||
fields[i] = p.llvmType(typ.Field(i).Type()).ll
|
||||
if n > 0 {
|
||||
fields = make([]llvm.Type, n)
|
||||
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 {
|
||||
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 {
|
||||
n := t.Len()
|
||||
ret := make([]llvm.Type, n)
|
||||
for i := 0; i < n; i++ {
|
||||
ret[i] = p.llvmType(t.At(i).Type()).ll
|
||||
func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) {
|
||||
if n > 0 {
|
||||
ret = make([]llvm.Type, n)
|
||||
for i := 0; i < n; i++ {
|
||||
ret[i] = p.llvmType(t.At(i).Type()).ll
|
||||
}
|
||||
}
|
||||
return ret
|
||||
return
|
||||
}
|
||||
|
||||
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()
|
||||
var ret llvm.Type
|
||||
switch nret := out.Len(); nret {
|
||||
@@ -230,7 +259,7 @@ func (p Program) toLLVMFunc(sig *types.Signature) Type {
|
||||
default:
|
||||
ret = p.toLLVMTuple(out)
|
||||
}
|
||||
ft := llvm.FunctionType(ret, params, sig.Variadic())
|
||||
ft := llvm.FunctionType(ret, params, hasVArg)
|
||||
return &aType{ft, sig, vkFunc}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user