From 013b3759049f15f4de2fab51c5b96ff7ac89f5c6 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 16 Apr 2018 17:04:49 +0200 Subject: [PATCH] Add type methods --- src/examples/hello/hello.go | 6 +++++- tgo.go | 42 ++++++++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/examples/hello/hello.go b/src/examples/hello/hello.go index 095ea22f..f5d35cc5 100644 --- a/src/examples/hello/hello.go +++ b/src/examples/hello/hello.go @@ -5,6 +5,10 @@ type Thing struct { name string } +func (t Thing) String() string { + return t.name +} + const SIX = 6 func main() { @@ -16,7 +20,7 @@ func main() { println("sumrange(100) =", sumrange(100)) thing := Thing{"foo"} - println("thing:", thing.name) + println("thing:", thing.String()) } func calculateAnswer() int { diff --git a/tgo.go b/tgo.go index 404e61a8..223f58aa 100644 --- a/tgo.go +++ b/tgo.go @@ -174,7 +174,15 @@ func (c *Compiler) Parse(pkgName string) error { global.SetLinkage(llvm.PrivateLinkage) } case *ssa.Type: - // TODO + ms := program.MethodSets.MethodSet(member.Type()) + for i := 0; i < ms.Len(); i++ { + fn := program.MethodValue(ms.At(i)) + frame, err := c.parseFuncDecl(pkgPrefix, fn) + if err != nil { + return err + } + frames[fn] = frame + } default: return errors.New("todo: member: " + fmt.Sprintf("%#v", member)) } @@ -185,7 +193,8 @@ func (c *Compiler) Parse(pkgName string) error { member := pkg.Members[name] fmt.Println("member:", member.Token(), member) - if member, ok := member.(*ssa.Function); ok { + switch member := member.(type) { + case *ssa.Function: if member.Blocks == nil { continue // external function } @@ -193,6 +202,15 @@ func (c *Compiler) Parse(pkgName string) error { if err != nil { return err } + case *ssa.Type: + ms := program.MethodSets.MethodSet(member.Type()) + for i := 0; i < ms.Len(); i++ { + fn := program.MethodValue(ms.At(i)) + err := c.parseFunc(frames[fn], fn) + if err != nil { + return err + } + } } } } @@ -241,15 +259,19 @@ func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) { } } -func (c *Compiler) getPackageRelativeName(frame *Frame, name string) string { - if strings.IndexByte(name, '.') == -1 { - name = frame.pkgPrefix + "." + name +func (c *Compiler) getFunctionName(pkgPrefix string, fn *ssa.Function) string { + if fn.Signature.Recv() != nil { + // Method on a defined type. + typeName := fn.Params[0].Type().(*types.Named).Obj().Name() + return pkgPrefix + "." + typeName + "." + fn.Name() + } else { + // Bare function. + return pkgPrefix + "." + fn.Name() } - return name } func (c *Compiler) parseFuncDecl(pkgPrefix string, f *ssa.Function) (*Frame, error) { - name := pkgPrefix + "." + f.Name() + name := c.getFunctionName(pkgPrefix, f) frame := &Frame{ pkgPrefix: pkgPrefix, name: name, @@ -413,7 +435,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, instr *ssa.CallCommon, call *ssa.B func (c *Compiler) parseFunctionCall(frame *Frame, call *ssa.CallCommon, fn *ssa.Function) (llvm.Value, error) { fmt.Printf(" function: %s\n", fn) - name := c.getPackageRelativeName(frame, fn.Name()) + name := c.getFunctionName(frame.pkgPrefix, fn) target := c.mod.NamedFunction(name) if target.IsNil() { return llvm.Value{}, errors.New("undefined function: " + name) @@ -484,7 +506,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { } return c.builder.CreateGEP(val, indices, ""), nil case *ssa.Global: - return c.mod.NamedGlobal(c.getPackageRelativeName(frame, expr.Name())), nil + return c.mod.NamedGlobal(expr.Name()), nil case *ssa.Parameter: llvmFn := c.mod.NamedFunction(frame.name) return llvmFn.Param(frame.params[expr]), nil @@ -559,7 +581,7 @@ func (c *Compiler) parseConst(expr *ssa.Const) (llvm.Value, error) { case constant.String: str := constant.StringVal(expr.Value) strLen := llvm.ConstInt(c.stringLenType, uint64(len(str)), false) - strPtr := c.builder.CreateGlobalStringPtr(str, ".str") + strPtr := c.builder.CreateGlobalStringPtr(str, ".str") // TODO: remove \0 at end strObj := llvm.ConstStruct([]llvm.Value{strLen, strPtr}, false) return strObj, nil case constant.Int: