compiler: refactor function calling

This commit is contained in:
Ayke van Laethem
2019-11-23 21:36:26 +01:00
committed by Ron Evans
parent d46934d1f1
commit d752e66be5
6 changed files with 198 additions and 192 deletions
+29 -29
View File
@@ -18,8 +18,8 @@ import (
// func ReadRegister(name string) uintptr
//
// The register name must be a constant, for example "sp".
func (c *Compiler) emitReadRegister(name string, args []ssa.Value) (llvm.Value, error) {
fnType := llvm.FunctionType(c.uintptrType, []llvm.Type{}, false)
func (b *builder) createReadRegister(name string, args []ssa.Value) (llvm.Value, error) {
fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{}, false)
regname := constant.StringVal(args[0].(*ssa.Const).Value)
var asm string
switch name {
@@ -31,7 +31,7 @@ func (c *Compiler) emitReadRegister(name string, args []ssa.Value) (llvm.Value,
panic("unknown architecture")
}
target := llvm.InlineAsm(fnType, asm, "=r", false, false, 0)
return c.builder.CreateCall(target, nil, ""), nil
return b.CreateCall(target, nil, ""), nil
}
// This is a compiler builtin, which emits a piece of inline assembly with no
@@ -41,12 +41,12 @@ func (c *Compiler) emitReadRegister(name string, args []ssa.Value) (llvm.Value,
// func Asm(asm string)
//
// The provided assembly must be a constant.
func (c *Compiler) emitAsm(args []ssa.Value) (llvm.Value, error) {
func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
// Magic function: insert inline assembly instead of calling it.
fnType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{}, false)
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{}, false)
asm := constant.StringVal(args[0].(*ssa.Const).Value)
target := llvm.InlineAsm(fnType, asm, "", true, false, 0)
return c.builder.CreateCall(target, nil, ""), nil
return b.CreateCall(target, nil, ""), nil
}
// This is a compiler builtin, which allows assembly to be called in a flexible
@@ -63,7 +63,7 @@ func (c *Compiler) emitAsm(args []ssa.Value) (llvm.Value, error) {
// "value": 1
// "result": &dest,
// })
func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) {
func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) {
asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)
registers := map[string]llvm.Value{}
registerMap := instr.Args[1].(*ssa.MakeMap)
@@ -73,17 +73,17 @@ func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value,
// ignore
case *ssa.MapUpdate:
if r.Block() != registerMap.Block() {
return llvm.Value{}, c.makeError(instr.Pos(), "register value map must be created in the same basic block")
return llvm.Value{}, b.makeError(instr.Pos(), "register value map must be created in the same basic block")
}
key := constant.StringVal(r.Key.(*ssa.Const).Value)
//println("value:", r.Value.(*ssa.MakeInterface).X.String())
registers[key] = frame.getValue(r.Value.(*ssa.MakeInterface).X)
registers[key] = b.getValue(r.Value.(*ssa.MakeInterface).X)
case *ssa.Call:
if r.Common() == instr {
break
}
default:
return llvm.Value{}, c.makeError(instr.Pos(), "don't know how to handle argument to inline assembly: "+r.String())
return llvm.Value{}, b.makeError(instr.Pos(), "don't know how to handle argument to inline assembly: "+r.String())
}
}
// TODO: handle dollar signs in asm string
@@ -98,7 +98,7 @@ func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value,
name := s[1 : len(s)-1]
if _, ok := registers[name]; !ok {
if err == nil {
err = c.makeError(instr.Pos(), "unknown register name: "+name)
err = b.makeError(instr.Pos(), "unknown register name: "+name)
}
return s
}
@@ -112,7 +112,7 @@ func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value,
case llvm.PointerTypeKind:
constraints = append(constraints, "*m")
default:
err = c.makeError(instr.Pos(), "unknown type in inline assembly for value: "+name)
err = b.makeError(instr.Pos(), "unknown type in inline assembly for value: "+name)
return s
}
}
@@ -121,9 +121,9 @@ func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value,
if err != nil {
return llvm.Value{}, err
}
fnType := llvm.FunctionType(c.ctx.VoidType(), argTypes, false)
fnType := llvm.FunctionType(b.ctx.VoidType(), argTypes, false)
target := llvm.InlineAsm(fnType, asmString, strings.Join(constraints, ","), true, false, 0)
return c.builder.CreateCall(target, args, ""), nil
return b.CreateCall(target, args, ""), nil
}
// This is a compiler builtin which emits an inline SVCall instruction. It can
@@ -137,7 +137,7 @@ func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value,
//
// The num parameter must be a constant. All other parameters may be any scalar
// value supported by LLVM inline assembly.
func (c *Compiler) emitSVCall(frame *Frame, args []ssa.Value) (llvm.Value, error) {
func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) {
num, _ := constant.Uint64Val(args[0].(*ssa.Const).Value)
llvmArgs := []llvm.Value{}
argTypes := []llvm.Type{}
@@ -150,7 +150,7 @@ func (c *Compiler) emitSVCall(frame *Frame, args []ssa.Value) (llvm.Value, error
} else {
constraints += ",{r" + strconv.Itoa(i) + "}"
}
llvmValue := frame.getValue(arg)
llvmValue := b.getValue(arg)
llvmArgs = append(llvmArgs, llvmValue)
argTypes = append(argTypes, llvmValue.Type())
}
@@ -158,9 +158,9 @@ func (c *Compiler) emitSVCall(frame *Frame, args []ssa.Value) (llvm.Value, error
// clobbered. r0 is used as an output register so doesn't have to be
// marked as clobbered.
constraints += ",~{r1},~{r2},~{r3}"
fnType := llvm.FunctionType(c.uintptrType, argTypes, false)
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0)
return c.builder.CreateCall(target, llvmArgs, ""), nil
return b.CreateCall(target, llvmArgs, ""), nil
}
// This is a compiler builtin which emits CSR instructions. It can be one of:
@@ -172,38 +172,38 @@ func (c *Compiler) emitSVCall(frame *Frame, args []ssa.Value) (llvm.Value, error
//
// The csr parameter (method receiver) must be a constant. Other parameter can
// be any value.
func (c *Compiler) emitCSROperation(frame *Frame, call *ssa.CallCommon) (llvm.Value, error) {
func (b *builder) emitCSROperation(call *ssa.CallCommon) (llvm.Value, error) {
csrConst, ok := call.Args[0].(*ssa.Const)
if !ok {
return llvm.Value{}, c.makeError(call.Pos(), "CSR must be constant")
return llvm.Value{}, b.makeError(call.Pos(), "CSR must be constant")
}
csr := csrConst.Uint64()
switch name := call.StaticCallee().Name(); name {
case "Get":
// Note that this instruction may have side effects, and thus must be
// marked as such.
fnType := llvm.FunctionType(c.uintptrType, nil, false)
fnType := llvm.FunctionType(b.uintptrType, nil, false)
asm := fmt.Sprintf("csrr $0, %d", csr)
target := llvm.InlineAsm(fnType, asm, "=r", true, false, 0)
return c.builder.CreateCall(target, nil, ""), nil
return b.CreateCall(target, nil, ""), nil
case "Set":
fnType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.uintptrType}, false)
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.uintptrType}, false)
asm := fmt.Sprintf("csrw %d, $0", csr)
target := llvm.InlineAsm(fnType, asm, "r", true, false, 0)
return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil
case "SetBits":
// Note: it may be possible to optimize this to csrrsi in many cases.
fnType := llvm.FunctionType(c.uintptrType, []llvm.Type{c.uintptrType}, false)
fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false)
asm := fmt.Sprintf("csrrs $0, %d, $1", csr)
target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0)
return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil
case "ClearBits":
// Note: it may be possible to optimize this to csrrci in many cases.
fnType := llvm.FunctionType(c.uintptrType, []llvm.Type{c.uintptrType}, false)
fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false)
asm := fmt.Sprintf("csrrc $0, %d, $1", csr)
target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0)
return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil
default:
return llvm.Value{}, c.makeError(call.Pos(), "unknown CSR operation: "+name)
return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation: "+name)
}
}