compiler: Implement register loads and stores
The way it works is somewhat of a hack, though. But it works for now.
Этот коммит содержится в:
родитель
8c426b406d
коммит
01602309fd
1 изменённых файлов: 26 добавлений и 4 удалений
30
tgo.go
30
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
|
||||||
return c.builder.CreateLoad(x, ""), nil
|
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
|
||||||
|
}
|
||||||
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:
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче