compiler: Implement register loads and stores

The way it works is somewhat of a hack, though. But it works for now.
Этот коммит содержится в:
Ayke van Laethem 2018-05-05 19:17:23 +02:00
родитель 8c426b406d
коммит 01602309fd

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

@ -628,15 +628,24 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
return errors.New("todo: return value") return errors.New("todo: return value")
} }
case *ssa.Store: case *ssa.Store:
addr, err := c.parseExpr(frame, instr.Addr) llvmAddr, err := c.parseExpr(frame, instr.Addr)
if err != nil { if err != nil {
return err return err
} }
val, err := c.parseExpr(frame, instr.Val) llvmVal, err := c.parseExpr(frame, instr.Val)
if err != nil { if err != nil {
return err return err
} }
c.builder.CreateStore(val, addr) valType := instr.Addr.Type().(*types.Pointer).Elem()
if valType, ok := valType.(*types.Named); ok && valType.Obj().Name() == "__reg" {
// Magic type name to transform this store to a register store.
registerAddr := c.builder.CreateLoad(llvmAddr, "")
ptr := c.builder.CreateIntToPtr(registerAddr, llvmAddr.Type(), "")
store := c.builder.CreateStore(llvmVal, ptr)
store.SetVolatile(true)
} else {
c.builder.CreateStore(llvmVal, llvmAddr)
}
return nil return nil
default: default:
return errors.New("unknown instruction: " + fmt.Sprintf("%#v", instr)) return errors.New("unknown instruction: " + fmt.Sprintf("%#v", instr))
@ -1139,7 +1148,20 @@ func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
case token.SUB: // -x case token.SUB: // -x
return c.builder.CreateSub(llvm.ConstInt(x.Type(), 0, false), x, ""), nil return c.builder.CreateSub(llvm.ConstInt(x.Type(), 0, false), x, ""), nil
case token.MUL: // *x, dereference pointer case token.MUL: // *x, dereference pointer
valType := unop.X.Type().(*types.Pointer).Elem()
if valType, ok := valType.(*types.Named); ok && valType.Obj().Name() == "__reg" {
// Magic type name: treat the value as a register pointer.
register := unop.X.(*ssa.FieldAddr)
global := register.X.(*ssa.Global)
llvmGlobal := c.mod.NamedGlobal(pkgPrefix(global.Pkg) + "." + global.Name())
llvmAddr := c.builder.CreateExtractValue(llvmGlobal.Initializer(), register.Field, "")
ptr := llvm.ConstIntToPtr(llvmAddr, x.Type())
load := c.builder.CreateLoad(ptr, "")
load.SetVolatile(true)
return load, nil
} else {
return c.builder.CreateLoad(x, ""), nil return c.builder.CreateLoad(x, ""), nil
}
case token.XOR: // ^x, toggle all bits in integer case token.XOR: // ^x, toggle all bits in integer
return c.builder.CreateXor(x, llvm.ConstInt(x.Type(), ^uint64(0), false), ""), nil return c.builder.CreateXor(x, llvm.ConstInt(x.Type(), ^uint64(0), false), ""), nil
default: default: