diff --git a/ssa/decl.go b/ssa/decl.go index a42f9cb6..83b3bbb2 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -17,6 +17,8 @@ package ssa import ( + "go/types" + "github.com/goplus/llvm" ) @@ -105,11 +107,32 @@ type aFunction struct { Type prog Program + + params []Type } type Function = *aFunction -func (p *aFunction) MakeBody(label string) Builder { +func newFunction(fn llvm.Value, t Type, prog Program) Function { + ret := &aFunction{fn, t, prog, newParams(t, prog)} + return ret +} + +func newParams(fn Type, prog Program) []Type { + in := fn.t.(*types.Signature).Params() + n := in.Len() + ret := make([]Type, n) + for i := 0; i < n; i++ { + ret[i] = prog.llvmType(in.At(i).Type()) + } + return ret +} + +func (p Function) Param(i int) Expr { + return Expr{p.impl.Param(i), p.params[i]} +} + +func (p Function) MakeBody(label string) Builder { body := llvm.AddBasicBlock(p.impl, label) prog := p.prog b := prog.ctx.NewBuilder() diff --git a/ssa/package.go b/ssa/package.go index f38e4565..2ebb9015 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -114,7 +114,7 @@ func (p Package) NewVar(name string, typ types.Type) Global { func (p Package) NewFunc(name string, sig *types.Signature) Function { t := p.prog.llvmSignature(sig) fn := llvm.AddFunction(p.mod, name, t.ll) - return &aFunction{fn, t, p.prog} + return newFunction(fn, t, p.prog) } func (p Package) String() string { diff --git a/ssa/ssa_test.go b/ssa/ssa_test.go index 49adf334..97e91028 100644 --- a/ssa/ssa_test.go +++ b/ssa/ssa_test.go @@ -95,15 +95,37 @@ declare void @fn(i64) func TestBasicFunc(t *testing.T) { prog := NewProgram(nil) pkg := prog.NewPackage("bar", "foo/bar") - rets := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int])) - sig := types.NewSignatureType(nil, nil, nil, nil, rets, false) - b := pkg.NewFunc("fn", sig).MakeBody("") - b.Return(prog.Val(1)) + params := types.NewTuple( + types.NewVar(0, nil, "a", types.Typ[types.Int]), + types.NewVar(0, nil, "b", types.Typ[types.Float64])) + rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int])) + sig := types.NewSignatureType(nil, nil, nil, params, rets, false) + pkg.NewFunc("fn", sig).MakeBody(""). + Return(prog.Val(1)) assertPkg(t, pkg, `; ModuleID = 'foo/bar' source_filename = "foo/bar" -define i64 @fn() { +define i64 @fn(i64 %0, double %1) { ret i64 1 } `) } + +func TestFuncParam(t *testing.T) { + prog := NewProgram(nil) + pkg := prog.NewPackage("bar", "foo/bar") + params := types.NewTuple( + types.NewVar(0, nil, "a", types.Typ[types.Int]), + types.NewVar(0, nil, "b", types.Typ[types.Float64])) + rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int])) + sig := types.NewSignatureType(nil, nil, nil, params, rets, false) + fn := pkg.NewFunc("fn", sig) + fn.MakeBody("").Return(fn.Param(1)) + assertPkg(t, pkg, `; ModuleID = 'foo/bar' +source_filename = "foo/bar" + +define i64 @fn(i64 %0, double %1) { + ret double %1 +} +`) +}