Этот коммит содержится в:
Ayke van Laethem 2018-04-16 01:01:11 +02:00
родитель de0ff3b3af
коммит d555ad93d7
2 изменённых файлов: 69 добавлений и 8 удалений

Просмотреть файл

@ -1,6 +1,10 @@
package main package main
type Thing struct {
name string
}
const SIX = 6 const SIX = 6
func main() { func main() {
@ -10,6 +14,9 @@ func main() {
println("3 + 12 =", add(3, 12)) println("3 + 12 =", add(3, 12))
println("fib(11) =", fib(11)) println("fib(11) =", fib(11))
println("sumrange(100) =", sumrange(100)) println("sumrange(100) =", sumrange(100))
thing := Thing{"foo"}
println("thing:", thing.name)
} }
func calculateAnswer() int { func calculateAnswer() int {

70
tgo.go
Просмотреть файл

@ -173,6 +173,8 @@ func (c *Compiler) Parse(pkgName string) error {
if ast.IsExported(member.Name()) { if ast.IsExported(member.Name()) {
global.SetLinkage(llvm.PrivateLinkage) global.SetLinkage(llvm.PrivateLinkage)
} }
case *ssa.Type:
// TODO
default: default:
return errors.New("todo: member: " + fmt.Sprintf("%#v", member)) return errors.New("todo: member: " + fmt.Sprintf("%#v", member))
} }
@ -199,6 +201,7 @@ func (c *Compiler) Parse(pkgName string) error {
} }
func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) { func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) {
fmt.Println(" type:", goType)
switch typ := goType.(type) { switch typ := goType.(type) {
case *types.Basic: case *types.Basic:
switch typ.Kind() { switch typ.Kind() {
@ -208,17 +211,31 @@ func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) {
return c.intType, nil return c.intType, nil
case types.Int32: case types.Int32:
return llvm.Int32Type(), nil return llvm.Int32Type(), nil
case types.String:
return c.stringType, nil
case types.UnsafePointer: case types.UnsafePointer:
return llvm.PointerType(llvm.Int8Type(), 0), nil return llvm.PointerType(llvm.Int8Type(), 0), nil
default: default:
return llvm.Type{}, errors.New("todo: unknown basic type: " + fmt.Sprintf("%#v", typ)) return llvm.Type{}, errors.New("todo: unknown basic type: " + fmt.Sprintf("%#v", typ))
} }
case *types.Named:
return c.getLLVMType(typ.Underlying())
case *types.Pointer: case *types.Pointer:
ptrTo, err := c.getLLVMType(typ.Elem()) ptrTo, err := c.getLLVMType(typ.Elem())
if err != nil { if err != nil {
return llvm.Type{}, err return llvm.Type{}, err
} }
return llvm.PointerType(ptrTo, 0), nil return llvm.PointerType(ptrTo, 0), nil
case *types.Struct:
members := make([]llvm.Type, typ.NumFields())
for i := 0; i < typ.NumFields(); i++ {
member, err := c.getLLVMType(typ.Field(i).Type())
if err != nil {
return llvm.Type{}, err
}
members[i] = member
}
return llvm.StructType(members, false), nil
default: default:
return llvm.Type{}, errors.New("todo: unknown type: " + fmt.Sprintf("%#v", goType)) return llvm.Type{}, errors.New("todo: unknown type: " + fmt.Sprintf("%#v", goType))
} }
@ -339,6 +356,17 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
} else { } else {
return errors.New("todo: return value") return errors.New("todo: return value")
} }
case *ssa.Store:
addr, err := c.parseExpr(frame, instr.Addr)
if err != nil {
return err
}
val, err := c.parseExpr(frame, instr.Val)
if err != nil {
return err
}
c.builder.CreateStore(val, addr)
return nil
default: default:
return errors.New("unknown instruction: " + fmt.Sprintf("%#v", instr)) return errors.New("unknown instruction: " + fmt.Sprintf("%#v", instr))
} }
@ -355,17 +383,22 @@ func (c *Compiler) parseBuiltin(frame *Frame, instr *ssa.CallCommon, call *ssa.B
c.builder.CreateCall(c.printspaceFunc, nil, "") c.builder.CreateCall(c.printspaceFunc, nil, "")
} }
fmt.Printf(" arg: %s\n", arg); fmt.Printf(" arg: %s\n", arg);
expr, err := c.parseExpr(frame, arg) value, err := c.parseExpr(frame, arg)
if err != nil { if err != nil {
return llvm.Value{}, err return llvm.Value{}, err
} }
switch expr.Type() { switch typ := arg.Type().(type) {
case c.stringType: case *types.Basic:
c.builder.CreateCall(c.printstringFunc, []llvm.Value{expr}, "") switch typ.Kind() {
case c.intType: case types.Int, types.Int32: // TODO: assumes a 32-bit int type
c.builder.CreateCall(c.printintFunc, []llvm.Value{expr}, "") c.builder.CreateCall(c.printintFunc, []llvm.Value{value}, "")
case types.String:
c.builder.CreateCall(c.printstringFunc, []llvm.Value{value}, "")
default: default:
return llvm.Value{}, errors.New("unknown arg type") return llvm.Value{}, errors.New("unknown basic arg type: " + fmt.Sprintf("%#v", typ))
}
default:
return llvm.Value{}, errors.New("unknown arg type: " + fmt.Sprintf("%#v", typ))
} }
} }
if name == "println" { if name == "println" {
@ -423,12 +456,31 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
} }
switch expr := expr.(type) { switch expr := expr.(type) {
case *ssa.Alloc:
if expr.Heap {
return llvm.Value{}, errors.New("todo: heap alloc")
}
typ, err := c.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
if err != nil {
return llvm.Value{}, err
}
return c.builder.CreateAlloca(typ, expr.Comment), nil
case *ssa.Const: case *ssa.Const:
return c.parseConst(expr) return c.parseConst(expr)
case *ssa.BinOp: case *ssa.BinOp:
return c.parseBinOp(frame, expr) return c.parseBinOp(frame, expr)
case *ssa.Call: case *ssa.Call:
return c.parseCall(frame, expr) return c.parseCall(frame, expr)
case *ssa.FieldAddr:
val, err := c.parseExpr(frame, expr.X)
if err != nil {
return llvm.Value{}, err
}
indices := []llvm.Value{
llvm.ConstInt(llvm.Int32Type(), 0, false),
llvm.ConstInt(llvm.Int32Type(), uint64(expr.Field), false),
}
return c.builder.CreateGEP(val, indices, ""), nil
case *ssa.Global: case *ssa.Global:
return c.mod.NamedGlobal(c.getPackageRelativeName(frame, expr.Name())), nil return c.mod.NamedGlobal(c.getPackageRelativeName(frame, expr.Name())), nil
case *ssa.Parameter: case *ssa.Parameter:
@ -522,8 +574,10 @@ func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
return llvm.Value{}, err return llvm.Value{}, err
} }
switch unop.Op { switch unop.Op {
case token.NOT: case token.NOT: // !
return c.builder.CreateNot(x, ""), nil return c.builder.CreateNot(x, ""), nil
case token.MUL: // *ptr, dereference pointer
return c.builder.CreateLoad(x, ""), nil
default: default:
return llvm.Value{}, errors.New("todo: unknown unop") return llvm.Value{}, errors.New("todo: unknown unop")
} }