compiler: rename Compiler.getValue -> builder.getValue

This is a fairly big commit, but it actually changes very little.
getValue should really be a property of the builder (or frame), where
the previously created instructions are kept.
Этот коммит содержится в:
Ayke van Laethem 2019-11-23 00:01:20 +01:00 коммит произвёл Ron Evans
родитель 840acdd316
коммит 349ecf1736
13 изменённых файлов: 122 добавлений и 110 удалений

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

@ -14,7 +14,7 @@ import (
func (c *Compiler) emitMakeChan(frame *Frame, expr *ssa.MakeChan) llvm.Value { func (c *Compiler) emitMakeChan(frame *Frame, expr *ssa.MakeChan) llvm.Value {
elementSize := c.targetData.TypeAllocSize(c.getLLVMType(expr.Type().(*types.Chan).Elem())) elementSize := c.targetData.TypeAllocSize(c.getLLVMType(expr.Type().(*types.Chan).Elem()))
elementSizeValue := llvm.ConstInt(c.uintptrType, elementSize, false) elementSizeValue := llvm.ConstInt(c.uintptrType, elementSize, false)
bufSize := c.getValue(frame, expr.Size) bufSize := frame.getValue(expr.Size)
c.emitChanBoundsCheck(frame, elementSize, bufSize, expr.Size.Type().Underlying().(*types.Basic), expr.Pos()) c.emitChanBoundsCheck(frame, elementSize, bufSize, expr.Size.Type().Underlying().(*types.Basic), expr.Pos())
if bufSize.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { if bufSize.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
bufSize = c.builder.CreateZExt(bufSize, c.uintptrType, "") bufSize = c.builder.CreateZExt(bufSize, c.uintptrType, "")
@ -27,8 +27,8 @@ func (c *Compiler) emitMakeChan(frame *Frame, expr *ssa.MakeChan) llvm.Value {
// emitChanSend emits a pseudo chan send operation. It is lowered to the actual // emitChanSend emits a pseudo chan send operation. It is lowered to the actual
// channel send operation during goroutine lowering. // channel send operation during goroutine lowering.
func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) { func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) {
ch := c.getValue(frame, instr.Chan) ch := frame.getValue(instr.Chan)
chanValue := c.getValue(frame, instr.X) chanValue := frame.getValue(instr.X)
// store value-to-send // store value-to-send
valueType := c.getLLVMType(instr.X.Type()) valueType := c.getLLVMType(instr.X.Type())
@ -48,7 +48,7 @@ func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) {
// actual channel receive operation during goroutine lowering. // actual channel receive operation during goroutine lowering.
func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) llvm.Value { func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) llvm.Value {
valueType := c.getLLVMType(unop.X.Type().(*types.Chan).Elem()) valueType := c.getLLVMType(unop.X.Type().(*types.Chan).Elem())
ch := c.getValue(frame, unop.X) ch := frame.getValue(unop.X)
// Allocate memory to receive into. // Allocate memory to receive into.
valueAlloca, valueAllocaCast, valueAllocaSize := c.createTemporaryAlloca(valueType, "chan.value") valueAlloca, valueAllocaCast, valueAllocaSize := c.createTemporaryAlloca(valueType, "chan.value")
@ -70,7 +70,7 @@ func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) llvm.Value {
// emitChanClose closes the given channel. // emitChanClose closes the given channel.
func (c *Compiler) emitChanClose(frame *Frame, param ssa.Value) { func (c *Compiler) emitChanClose(frame *Frame, param ssa.Value) {
ch := c.getValue(frame, param) ch := frame.getValue(param)
c.createRuntimeCall("chanClose", []llvm.Value{ch}, "") c.createRuntimeCall("chanClose", []llvm.Value{ch}, "")
} }
@ -111,7 +111,7 @@ func (c *Compiler) emitSelect(frame *Frame, expr *ssa.Select) llvm.Value {
var selectStates []llvm.Value var selectStates []llvm.Value
chanSelectStateType := c.getLLVMRuntimeType("chanSelectState") chanSelectStateType := c.getLLVMRuntimeType("chanSelectState")
for _, state := range expr.States { for _, state := range expr.States {
ch := c.getValue(frame, state.Chan) ch := frame.getValue(state.Chan)
selectState := llvm.ConstNull(chanSelectStateType) selectState := llvm.ConstNull(chanSelectStateType)
selectState = c.builder.CreateInsertValue(selectState, ch, 0, "") selectState = c.builder.CreateInsertValue(selectState, ch, 0, "")
switch state.Dir { switch state.Dir {
@ -128,7 +128,7 @@ func (c *Compiler) emitSelect(frame *Frame, expr *ssa.Select) llvm.Value {
case types.SendOnly: case types.SendOnly:
// Store this value in an alloca and put a pointer to this alloca // Store this value in an alloca and put a pointer to this alloca
// in the send state. // in the send state.
sendValue := c.getValue(frame, state.Send) sendValue := frame.getValue(state.Send)
alloca := llvmutil.CreateEntryBlockAlloca(c.builder, sendValue.Type(), "select.send.value") alloca := llvmutil.CreateEntryBlockAlloca(c.builder, sendValue.Type(), "select.send.value")
c.builder.CreateStore(sendValue, alloca) c.builder.CreateStore(sendValue, alloca)
ptr := c.builder.CreateBitCast(alloca, c.i8ptrType, "") ptr := c.builder.CreateBitCast(alloca, c.i8ptrType, "")
@ -219,7 +219,7 @@ func (c *Compiler) emitSelect(frame *Frame, expr *ssa.Select) llvm.Value {
func (c *Compiler) getChanSelectResult(frame *Frame, expr *ssa.Extract) llvm.Value { func (c *Compiler) getChanSelectResult(frame *Frame, expr *ssa.Extract) llvm.Value {
if expr.Index == 0 { if expr.Index == 0 {
// index // index
value := c.getValue(frame, expr.Tuple) value := frame.getValue(expr.Tuple)
index := c.builder.CreateExtractValue(value, expr.Index, "") index := c.builder.CreateExtractValue(value, expr.Index, "")
if index.Type().IntTypeWidth() < c.intType.IntTypeWidth() { if index.Type().IntTypeWidth() < c.intType.IntTypeWidth() {
index = c.builder.CreateSExt(index, c.intType, "") index = c.builder.CreateSExt(index, c.intType, "")
@ -227,7 +227,7 @@ func (c *Compiler) getChanSelectResult(frame *Frame, expr *ssa.Extract) llvm.Val
return index return index
} else if expr.Index == 1 { } else if expr.Index == 1 {
// comma-ok // comma-ok
value := c.getValue(frame, expr.Tuple) value := frame.getValue(expr.Tuple)
return c.builder.CreateExtractValue(value, expr.Index, "") return c.builder.CreateExtractValue(value, expr.Index, "")
} else { } else {
// Select statements are (index, ok, ...) where ... is a number of // Select statements are (index, ok, ...) where ... is a number of

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

@ -53,6 +53,7 @@ type compilerContext struct {
uintptrType llvm.Type uintptrType llvm.Type
ir *ir.Program ir *ir.Program
diagnostics []error diagnostics []error
astComments map[string]*ast.CommentGroup
} }
type Compiler struct { type Compiler struct {
@ -60,7 +61,6 @@ type Compiler struct {
builder llvm.Builder builder llvm.Builder
initFuncs []llvm.Value initFuncs []llvm.Value
interfaceInvokeWrappers []interfaceInvokeWrapper interfaceInvokeWrappers []interfaceInvokeWrapper
astComments map[string]*ast.CommentGroup
} }
type Frame struct { type Frame struct {
@ -513,7 +513,7 @@ func isPointer(typ types.Type) bool {
} }
// Get the DWARF type for this Go type. // Get the DWARF type for this Go type.
func (c *Compiler) getDIType(typ types.Type) llvm.Metadata { func (c *compilerContext) getDIType(typ types.Type) llvm.Metadata {
if md, ok := c.ditypes[typ]; ok { if md, ok := c.ditypes[typ]; ok {
return md return md
} }
@ -524,7 +524,7 @@ func (c *Compiler) getDIType(typ types.Type) llvm.Metadata {
// createDIType creates a new DWARF type. Don't call this function directly, // createDIType creates a new DWARF type. Don't call this function directly,
// call getDIType instead. // call getDIType instead.
func (c *Compiler) createDIType(typ types.Type) llvm.Metadata { func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
llvmType := c.getLLVMType(typ) llvmType := c.getLLVMType(typ)
sizeInBytes := c.targetData.TypeAllocSize(llvmType) sizeInBytes := c.targetData.TypeAllocSize(llvmType)
switch typ := typ.(type) { switch typ := typ.(type) {
@ -836,7 +836,7 @@ func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix,
// getDIFile returns a DIFile metadata node for the given filename. It tries to // getDIFile returns a DIFile metadata node for the given filename. It tries to
// use one that was already created, otherwise it falls back to creating a new // use one that was already created, otherwise it falls back to creating a new
// one. // one.
func (c *Compiler) getDIFile(filename string) llvm.Metadata { func (c *compilerContext) getDIFile(filename string) llvm.Metadata {
if _, ok := c.difiles[filename]; !ok { if _, ok := c.difiles[filename]; !ok {
dir, file := filepath.Split(filename) dir, file := filepath.Split(filename)
if dir != "" { if dir != "" {
@ -988,7 +988,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
} }
dbgVar := c.getLocalVariable(frame, variable) dbgVar := c.getLocalVariable(frame, variable)
pos := c.ir.Program.Fset.Position(instr.Pos()) pos := c.ir.Program.Fset.Position(instr.Pos())
c.dibuilder.InsertValueAtEnd(c.getValue(frame, instr.X), dbgVar, c.dibuilder.CreateExpression(nil), llvm.DebugLoc{ c.dibuilder.InsertValueAtEnd(frame.getValue(instr.X), dbgVar, c.dibuilder.CreateExpression(nil), llvm.DebugLoc{
Line: uint(pos.Line), Line: uint(pos.Line),
Col: uint(pos.Column), Col: uint(pos.Column),
Scope: frame.difunc, Scope: frame.difunc,
@ -1013,7 +1013,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
for _, phi := range frame.phis { for _, phi := range frame.phis {
block := phi.ssa.Block() block := phi.ssa.Block()
for i, edge := range phi.ssa.Edges { for i, edge := range phi.ssa.Edges {
llvmVal := c.getValue(frame, edge) llvmVal := frame.getValue(edge)
llvmBlock := frame.blockExits[block.Preds[i]] llvmBlock := frame.blockExits[block.Preds[i]]
phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock}) phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock})
} }
@ -1051,7 +1051,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
// Get all function parameters to pass to the goroutine. // Get all function parameters to pass to the goroutine.
var params []llvm.Value var params []llvm.Value
for _, param := range instr.Call.Args { for _, param := range instr.Call.Args {
params = append(params, c.getValue(frame, param)) params = append(params, frame.getValue(param))
} }
// Start a new goroutine. // Start a new goroutine.
@ -1067,7 +1067,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
case *ssa.MakeClosure: case *ssa.MakeClosure:
// A goroutine call on a func value, but the callee is trivial to find. For // A goroutine call on a func value, but the callee is trivial to find. For
// example: immediately applied functions. // example: immediately applied functions.
funcValue := c.getValue(frame, value) funcValue := frame.getValue(value)
context = c.extractFuncContext(funcValue) context = c.extractFuncContext(funcValue)
default: default:
panic("StaticCallee returned an unexpected value") panic("StaticCallee returned an unexpected value")
@ -1080,7 +1080,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
// goroutine: // goroutine:
// * The function context, for closures. // * The function context, for closures.
// * The function pointer (for tasks). // * The function pointer (for tasks).
funcPtr, context := c.decodeFuncValue(c.getValue(frame, instr.Call.Value), instr.Call.Value.Type().(*types.Signature)) funcPtr, context := c.decodeFuncValue(frame.getValue(instr.Call.Value), instr.Call.Value.Type().(*types.Signature))
params = append(params, context) // context parameter params = append(params, context) // context parameter
switch c.Scheduler() { switch c.Scheduler() {
case "none", "coroutines": case "none", "coroutines":
@ -1096,7 +1096,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
c.addError(instr.Pos(), "todo: go on interface call") c.addError(instr.Pos(), "todo: go on interface call")
} }
case *ssa.If: case *ssa.If:
cond := c.getValue(frame, instr.Cond) cond := frame.getValue(instr.Cond)
block := instr.Block() block := instr.Block()
blockThen := frame.blockEntries[block.Succs[0]] blockThen := frame.blockEntries[block.Succs[0]]
blockElse := frame.blockEntries[block.Succs[1]] blockElse := frame.blockEntries[block.Succs[1]]
@ -1105,25 +1105,25 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
blockJump := frame.blockEntries[instr.Block().Succs[0]] blockJump := frame.blockEntries[instr.Block().Succs[0]]
c.builder.CreateBr(blockJump) c.builder.CreateBr(blockJump)
case *ssa.MapUpdate: case *ssa.MapUpdate:
m := c.getValue(frame, instr.Map) m := frame.getValue(instr.Map)
key := c.getValue(frame, instr.Key) key := frame.getValue(instr.Key)
value := c.getValue(frame, instr.Value) value := frame.getValue(instr.Value)
mapType := instr.Map.Type().Underlying().(*types.Map) mapType := instr.Map.Type().Underlying().(*types.Map)
c.emitMapUpdate(mapType.Key(), m, key, value, instr.Pos()) c.emitMapUpdate(mapType.Key(), m, key, value, instr.Pos())
case *ssa.Panic: case *ssa.Panic:
value := c.getValue(frame, instr.X) value := frame.getValue(instr.X)
c.createRuntimeCall("_panic", []llvm.Value{value}, "") c.createRuntimeCall("_panic", []llvm.Value{value}, "")
c.builder.CreateUnreachable() c.builder.CreateUnreachable()
case *ssa.Return: case *ssa.Return:
if len(instr.Results) == 0 { if len(instr.Results) == 0 {
c.builder.CreateRetVoid() c.builder.CreateRetVoid()
} else if len(instr.Results) == 1 { } else if len(instr.Results) == 1 {
c.builder.CreateRet(c.getValue(frame, instr.Results[0])) c.builder.CreateRet(frame.getValue(instr.Results[0]))
} else { } else {
// Multiple return values. Put them all in a struct. // Multiple return values. Put them all in a struct.
retVal := llvm.ConstNull(frame.fn.LLVMFn.Type().ElementType().ReturnType()) retVal := llvm.ConstNull(frame.fn.LLVMFn.Type().ElementType().ReturnType())
for i, result := range instr.Results { for i, result := range instr.Results {
val := c.getValue(frame, result) val := frame.getValue(result)
retVal = c.builder.CreateInsertValue(retVal, val, i, "") retVal = c.builder.CreateInsertValue(retVal, val, i, "")
} }
c.builder.CreateRet(retVal) c.builder.CreateRet(retVal)
@ -1133,8 +1133,8 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
case *ssa.Send: case *ssa.Send:
c.emitChanSend(frame, instr) c.emitChanSend(frame, instr)
case *ssa.Store: case *ssa.Store:
llvmAddr := c.getValue(frame, instr.Addr) llvmAddr := frame.getValue(instr.Addr)
llvmVal := c.getValue(frame, instr.Val) llvmVal := frame.getValue(instr.Val)
c.emitNilCheck(frame, llvmAddr, "store") c.emitNilCheck(frame, llvmAddr, "store")
if c.targetData.TypeAllocSize(llvmVal.Type()) == 0 { if c.targetData.TypeAllocSize(llvmVal.Type()) == 0 {
// nothing to store // nothing to store
@ -1149,8 +1149,8 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string, pos token.Pos) (llvm.Value, error) { func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string, pos token.Pos) (llvm.Value, error) {
switch callName { switch callName {
case "append": case "append":
src := c.getValue(frame, args[0]) src := frame.getValue(args[0])
elems := c.getValue(frame, args[1]) elems := frame.getValue(args[1])
srcBuf := c.builder.CreateExtractValue(src, 0, "append.srcBuf") srcBuf := c.builder.CreateExtractValue(src, 0, "append.srcBuf")
srcPtr := c.builder.CreateBitCast(srcBuf, c.i8ptrType, "append.srcPtr") srcPtr := c.builder.CreateBitCast(srcBuf, c.i8ptrType, "append.srcPtr")
srcLen := c.builder.CreateExtractValue(src, 1, "append.srcLen") srcLen := c.builder.CreateExtractValue(src, 1, "append.srcLen")
@ -1171,7 +1171,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
newSlice = c.builder.CreateInsertValue(newSlice, newCap, 2, "") newSlice = c.builder.CreateInsertValue(newSlice, newCap, 2, "")
return newSlice, nil return newSlice, nil
case "cap": case "cap":
value := c.getValue(frame, args[0]) value := frame.getValue(args[0])
var llvmCap llvm.Value var llvmCap llvm.Value
switch args[0].Type().(type) { switch args[0].Type().(type) {
case *types.Chan: case *types.Chan:
@ -1191,8 +1191,8 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
c.emitChanClose(frame, args[0]) c.emitChanClose(frame, args[0])
return llvm.Value{}, nil return llvm.Value{}, nil
case "complex": case "complex":
r := c.getValue(frame, args[0]) r := frame.getValue(args[0])
i := c.getValue(frame, args[1]) i := frame.getValue(args[1])
t := args[0].Type().Underlying().(*types.Basic) t := args[0].Type().Underlying().(*types.Basic)
var cplx llvm.Value var cplx llvm.Value
switch t.Kind() { switch t.Kind() {
@ -1207,8 +1207,8 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
cplx = c.builder.CreateInsertValue(cplx, i, 1, "") cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
return cplx, nil return cplx, nil
case "copy": case "copy":
dst := c.getValue(frame, args[0]) dst := frame.getValue(args[0])
src := c.getValue(frame, args[1]) src := frame.getValue(args[1])
dstLen := c.builder.CreateExtractValue(dst, 1, "copy.dstLen") dstLen := c.builder.CreateExtractValue(dst, 1, "copy.dstLen")
srcLen := c.builder.CreateExtractValue(src, 1, "copy.srcLen") srcLen := c.builder.CreateExtractValue(src, 1, "copy.srcLen")
dstBuf := c.builder.CreateExtractValue(dst, 0, "copy.dstArray") dstBuf := c.builder.CreateExtractValue(dst, 0, "copy.dstArray")
@ -1219,14 +1219,14 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
elemSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(elemType), false) elemSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(elemType), false)
return c.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil return c.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil
case "delete": case "delete":
m := c.getValue(frame, args[0]) m := frame.getValue(args[0])
key := c.getValue(frame, args[1]) key := frame.getValue(args[1])
return llvm.Value{}, c.emitMapDelete(args[1].Type(), m, key, pos) return llvm.Value{}, c.emitMapDelete(args[1].Type(), m, key, pos)
case "imag": case "imag":
cplx := c.getValue(frame, args[0]) cplx := frame.getValue(args[0])
return c.builder.CreateExtractValue(cplx, 1, "imag"), nil return c.builder.CreateExtractValue(cplx, 1, "imag"), nil
case "len": case "len":
value := c.getValue(frame, args[0]) value := frame.getValue(args[0])
var llvmLen llvm.Value var llvmLen llvm.Value
switch args[0].Type().Underlying().(type) { switch args[0].Type().Underlying().(type) {
case *types.Basic, *types.Slice: case *types.Basic, *types.Slice:
@ -1250,7 +1250,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
if i >= 1 && callName == "println" { if i >= 1 && callName == "println" {
c.createRuntimeCall("printspace", nil, "") c.createRuntimeCall("printspace", nil, "")
} }
value := c.getValue(frame, arg) value := frame.getValue(arg)
typ := arg.Type().Underlying() typ := arg.Type().Underlying()
switch typ := typ.(type) { switch typ := typ.(type) {
case *types.Basic: case *types.Basic:
@ -1303,13 +1303,13 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
} }
return llvm.Value{}, nil // print() or println() returns void return llvm.Value{}, nil // print() or println() returns void
case "real": case "real":
cplx := c.getValue(frame, args[0]) cplx := frame.getValue(args[0])
return c.builder.CreateExtractValue(cplx, 0, "real"), nil return c.builder.CreateExtractValue(cplx, 0, "real"), nil
case "recover": case "recover":
return c.createRuntimeCall("_recover", nil, ""), nil return c.createRuntimeCall("_recover", nil, ""), nil
case "ssa:wrapnilchk": case "ssa:wrapnilchk":
// TODO: do an actual nil check? // TODO: do an actual nil check?
return c.getValue(frame, args[0]), nil return frame.getValue(args[0]), nil
default: default:
return llvm.Value{}, c.makeError(pos, "todo: builtin: "+callName) return llvm.Value{}, c.makeError(pos, "todo: builtin: "+callName)
} }
@ -1318,7 +1318,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
func (c *Compiler) parseFunctionCall(frame *Frame, args []ssa.Value, llvmFn, context llvm.Value, exported bool) llvm.Value { func (c *Compiler) parseFunctionCall(frame *Frame, args []ssa.Value, llvmFn, context llvm.Value, exported bool) llvm.Value {
var params []llvm.Value var params []llvm.Value
for _, param := range args { for _, param := range args {
params = append(params, c.getValue(frame, param)) params = append(params, frame.getValue(param))
} }
if !exported { if !exported {
@ -1375,7 +1375,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
case *ssa.MakeClosure: case *ssa.MakeClosure:
// A call on a func value, but the callee is trivial to find. For // A call on a func value, but the callee is trivial to find. For
// example: immediately applied functions. // example: immediately applied functions.
funcValue := c.getValue(frame, value) funcValue := frame.getValue(value)
context = c.extractFuncContext(funcValue) context = c.extractFuncContext(funcValue)
default: default:
panic("StaticCallee returned an unexpected value") panic("StaticCallee returned an unexpected value")
@ -1388,7 +1388,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
case *ssa.Builtin: case *ssa.Builtin:
return c.parseBuiltin(frame, instr.Args, call.Name(), instr.Pos()) return c.parseBuiltin(frame, instr.Args, call.Name(), instr.Pos())
default: // function pointer default: // function pointer
value := c.getValue(frame, instr.Value) value := frame.getValue(instr.Value)
// This is a func value, which cannot be called directly. We have to // This is a func value, which cannot be called directly. We have to
// extract the function pointer and context first from the func value. // extract the function pointer and context first from the func value.
funcPtr, context := c.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature)) funcPtr, context := c.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature))
@ -1399,27 +1399,27 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
// getValue returns the LLVM value of a constant, function value, global, or // getValue returns the LLVM value of a constant, function value, global, or
// already processed SSA expression. // already processed SSA expression.
func (c *Compiler) getValue(frame *Frame, expr ssa.Value) llvm.Value { func (b *builder) getValue(expr ssa.Value) llvm.Value {
switch expr := expr.(type) { switch expr := expr.(type) {
case *ssa.Const: case *ssa.Const:
return frame.createConst(frame.fn.LinkName(), expr) return b.createConst(b.fn.LinkName(), expr)
case *ssa.Function: case *ssa.Function:
fn := c.ir.GetFunction(expr) fn := b.ir.GetFunction(expr)
if fn.IsExported() { if fn.IsExported() {
c.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String()) b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String())
return llvm.Undef(c.getLLVMType(expr.Type())) return llvm.Undef(b.getLLVMType(expr.Type()))
} }
return c.createFuncValue(fn.LLVMFn, llvm.Undef(c.i8ptrType), fn.Signature) return b.createFuncValue(fn.LLVMFn, llvm.Undef(b.i8ptrType), fn.Signature)
case *ssa.Global: case *ssa.Global:
value := c.getGlobal(expr) value := b.getGlobal(expr)
if value.IsNil() { if value.IsNil() {
c.addError(expr.Pos(), "global not found: "+expr.RelString(nil)) b.addError(expr.Pos(), "global not found: "+expr.RelString(nil))
return llvm.Undef(c.getLLVMType(expr.Type())) return llvm.Undef(b.getLLVMType(expr.Type()))
} }
return value return value
default: default:
// other (local) SSA value // other (local) SSA value
if value, ok := frame.locals[expr]; ok { if value, ok := b.locals[expr]; ok {
return value return value
} else { } else {
// indicates a compiler bug // indicates a compiler bug
@ -1458,8 +1458,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
return buf, nil return buf, nil
} }
case *ssa.BinOp: case *ssa.BinOp:
x := c.getValue(frame, expr.X) x := frame.getValue(expr.X)
y := c.getValue(frame, expr.Y) y := frame.getValue(expr.Y)
return frame.createBinOp(expr.Op, expr.X.Type(), x, y, expr.Pos()) return frame.createBinOp(expr.Op, expr.X.Type(), x, y, expr.Pos())
case *ssa.Call: case *ssa.Call:
// Passing the current task here to the subroutine. It is only used when // Passing the current task here to the subroutine. It is only used when
@ -1472,12 +1472,12 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
// This is different from how the official Go compiler works, because of // This is different from how the official Go compiler works, because of
// heap allocation and because it's easier to implement, see: // heap allocation and because it's easier to implement, see:
// https://research.swtch.com/interfaces // https://research.swtch.com/interfaces
return c.getValue(frame, expr.X), nil return frame.getValue(expr.X), nil
case *ssa.ChangeType: case *ssa.ChangeType:
// This instruction changes the type, but the underlying value remains // This instruction changes the type, but the underlying value remains
// the same. This is often a no-op, but sometimes we have to change the // the same. This is often a no-op, but sometimes we have to change the
// LLVM type as well. // LLVM type as well.
x := c.getValue(frame, expr.X) x := frame.getValue(expr.X)
llvmType := c.getLLVMType(expr.Type()) llvmType := c.getLLVMType(expr.Type())
if x.Type() == llvmType { if x.Type() == llvmType {
// Different Go type but same LLVM type (for example, named int). // Different Go type but same LLVM type (for example, named int).
@ -1506,20 +1506,20 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
case *ssa.Const: case *ssa.Const:
panic("const is not an expression") panic("const is not an expression")
case *ssa.Convert: case *ssa.Convert:
x := c.getValue(frame, expr.X) x := frame.getValue(expr.X)
return c.parseConvert(expr.X.Type(), expr.Type(), x, expr.Pos()) return c.parseConvert(expr.X.Type(), expr.Type(), x, expr.Pos())
case *ssa.Extract: case *ssa.Extract:
if _, ok := expr.Tuple.(*ssa.Select); ok { if _, ok := expr.Tuple.(*ssa.Select); ok {
return c.getChanSelectResult(frame, expr), nil return c.getChanSelectResult(frame, expr), nil
} }
value := c.getValue(frame, expr.Tuple) value := frame.getValue(expr.Tuple)
return c.builder.CreateExtractValue(value, expr.Index, ""), nil return c.builder.CreateExtractValue(value, expr.Index, ""), nil
case *ssa.Field: case *ssa.Field:
value := c.getValue(frame, expr.X) value := frame.getValue(expr.X)
result := c.builder.CreateExtractValue(value, expr.Field, "") result := c.builder.CreateExtractValue(value, expr.Field, "")
return result, nil return result, nil
case *ssa.FieldAddr: case *ssa.FieldAddr:
val := c.getValue(frame, expr.X) val := frame.getValue(expr.X)
// Check for nil pointer before calculating the address, from the spec: // Check for nil pointer before calculating the address, from the spec:
// > For an operand x of type T, the address operation &x generates a // > For an operand x of type T, the address operation &x generates a
// > pointer of type *T to x. [...] If the evaluation of x would cause a // > pointer of type *T to x. [...] If the evaluation of x would cause a
@ -1536,8 +1536,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
case *ssa.Global: case *ssa.Global:
panic("global is not an expression") panic("global is not an expression")
case *ssa.Index: case *ssa.Index:
array := c.getValue(frame, expr.X) array := frame.getValue(expr.X)
index := c.getValue(frame, expr.Index) index := frame.getValue(expr.Index)
// Check bounds. // Check bounds.
arrayLen := expr.X.Type().(*types.Array).Len() arrayLen := expr.X.Type().(*types.Array).Len()
@ -1554,8 +1554,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
c.emitLifetimeEnd(allocaPtr, allocaSize) c.emitLifetimeEnd(allocaPtr, allocaSize)
return result, nil return result, nil
case *ssa.IndexAddr: case *ssa.IndexAddr:
val := c.getValue(frame, expr.X) val := frame.getValue(expr.X)
index := c.getValue(frame, expr.Index) index := frame.getValue(expr.Index)
// Get buffer pointer and length // Get buffer pointer and length
var bufptr, buflen llvm.Value var bufptr, buflen llvm.Value
@ -1599,8 +1599,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
panic("unreachable") panic("unreachable")
} }
case *ssa.Lookup: case *ssa.Lookup:
value := c.getValue(frame, expr.X) value := frame.getValue(expr.X)
index := c.getValue(frame, expr.Index) index := frame.getValue(expr.Index)
switch xType := expr.X.Type().Underlying().(type) { switch xType := expr.X.Type().Underlying().(type) {
case *types.Basic: case *types.Basic:
// Value type must be a string, which is a basic type. // Value type must be a string, which is a basic type.
@ -1630,13 +1630,13 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
case *ssa.MakeClosure: case *ssa.MakeClosure:
return c.parseMakeClosure(frame, expr) return c.parseMakeClosure(frame, expr)
case *ssa.MakeInterface: case *ssa.MakeInterface:
val := c.getValue(frame, expr.X) val := frame.getValue(expr.X)
return c.parseMakeInterface(val, expr.X.Type(), expr.Pos()), nil return c.parseMakeInterface(val, expr.X.Type(), expr.Pos()), nil
case *ssa.MakeMap: case *ssa.MakeMap:
return c.emitMakeMap(frame, expr) return c.emitMakeMap(frame, expr)
case *ssa.MakeSlice: case *ssa.MakeSlice:
sliceLen := c.getValue(frame, expr.Len) sliceLen := frame.getValue(expr.Len)
sliceCap := c.getValue(frame, expr.Cap) sliceCap := frame.getValue(expr.Cap)
sliceType := expr.Type().Underlying().(*types.Slice) sliceType := expr.Type().Underlying().(*types.Slice)
llvmElemType := c.getLLVMType(sliceType.Elem()) llvmElemType := c.getLLVMType(sliceType.Elem())
elemSize := c.targetData.TypeAllocSize(llvmElemType) elemSize := c.targetData.TypeAllocSize(llvmElemType)
@ -1688,8 +1688,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
return slice, nil return slice, nil
case *ssa.Next: case *ssa.Next:
rangeVal := expr.Iter.(*ssa.Range).X rangeVal := expr.Iter.(*ssa.Range).X
llvmRangeVal := c.getValue(frame, rangeVal) llvmRangeVal := frame.getValue(rangeVal)
it := c.getValue(frame, expr.Iter) it := frame.getValue(expr.Iter)
if expr.IsString { if expr.IsString {
return c.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil return c.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
} else { // map } else { // map
@ -1728,14 +1728,14 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
case *ssa.Select: case *ssa.Select:
return c.emitSelect(frame, expr), nil return c.emitSelect(frame, expr), nil
case *ssa.Slice: case *ssa.Slice:
value := c.getValue(frame, expr.X) value := frame.getValue(expr.X)
var lowType, highType, maxType *types.Basic var lowType, highType, maxType *types.Basic
var low, high, max llvm.Value var low, high, max llvm.Value
if expr.Low != nil { if expr.Low != nil {
lowType = expr.Low.Type().Underlying().(*types.Basic) lowType = expr.Low.Type().Underlying().(*types.Basic)
low = c.getValue(frame, expr.Low) low = frame.getValue(expr.Low)
if low.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { if low.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
if lowType.Info()&types.IsUnsigned != 0 { if lowType.Info()&types.IsUnsigned != 0 {
low = c.builder.CreateZExt(low, c.uintptrType, "") low = c.builder.CreateZExt(low, c.uintptrType, "")
@ -1750,7 +1750,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
if expr.High != nil { if expr.High != nil {
highType = expr.High.Type().Underlying().(*types.Basic) highType = expr.High.Type().Underlying().(*types.Basic)
high = c.getValue(frame, expr.High) high = frame.getValue(expr.High)
if high.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { if high.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
if highType.Info()&types.IsUnsigned != 0 { if highType.Info()&types.IsUnsigned != 0 {
high = c.builder.CreateZExt(high, c.uintptrType, "") high = c.builder.CreateZExt(high, c.uintptrType, "")
@ -1764,7 +1764,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
if expr.Max != nil { if expr.Max != nil {
maxType = expr.Max.Type().Underlying().(*types.Basic) maxType = expr.Max.Type().Underlying().(*types.Basic)
max = c.getValue(frame, expr.Max) max = frame.getValue(expr.Max)
if max.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { if max.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
if maxType.Info()&types.IsUnsigned != 0 { if maxType.Info()&types.IsUnsigned != 0 {
max = c.builder.CreateZExt(max, c.uintptrType, "") max = c.builder.CreateZExt(max, c.uintptrType, "")
@ -2524,7 +2524,7 @@ func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, p
} }
func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) { func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
x := c.getValue(frame, unop.X) x := frame.getValue(unop.X)
switch unop.Op { switch unop.Op {
case token.NOT: // !x case token.NOT: // !x
return c.builder.CreateNot(x, ""), nil return c.builder.CreateNot(x, ""), nil

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

@ -91,12 +91,12 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
// Collect all values to be put in the struct (starting with // Collect all values to be put in the struct (starting with
// runtime._defer fields, followed by the call parameters). // runtime._defer fields, followed by the call parameters).
itf := c.getValue(frame, instr.Call.Value) // interface itf := frame.getValue(instr.Call.Value) // interface
receiverValue := c.builder.CreateExtractValue(itf, 1, "invoke.func.receiver") receiverValue := c.builder.CreateExtractValue(itf, 1, "invoke.func.receiver")
values = []llvm.Value{callback, next, receiverValue} values = []llvm.Value{callback, next, receiverValue}
valueTypes = append(valueTypes, c.i8ptrType) valueTypes = append(valueTypes, c.i8ptrType)
for _, arg := range instr.Call.Args { for _, arg := range instr.Call.Args {
val := c.getValue(frame, arg) val := frame.getValue(arg)
values = append(values, val) values = append(values, val)
valueTypes = append(valueTypes, val.Type()) valueTypes = append(valueTypes, val.Type())
} }
@ -115,7 +115,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
// runtime._defer fields). // runtime._defer fields).
values = []llvm.Value{callback, next} values = []llvm.Value{callback, next}
for _, param := range instr.Call.Args { for _, param := range instr.Call.Args {
llvmParam := c.getValue(frame, param) llvmParam := frame.getValue(param)
values = append(values, llvmParam) values = append(values, llvmParam)
valueTypes = append(valueTypes, llvmParam.Type()) valueTypes = append(valueTypes, llvmParam.Type())
} }
@ -127,7 +127,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
// pointer. // pointer.
// TODO: ignore this closure entirely and put pointers to the free // TODO: ignore this closure entirely and put pointers to the free
// variables directly in the defer struct, avoiding a memory allocation. // variables directly in the defer struct, avoiding a memory allocation.
closure := c.getValue(frame, instr.Call.Value) closure := frame.getValue(instr.Call.Value)
context := c.builder.CreateExtractValue(closure, 0, "") context := c.builder.CreateExtractValue(closure, 0, "")
// Get the callback number. // Get the callback number.
@ -143,7 +143,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
// context pointer). // context pointer).
values = []llvm.Value{callback, next} values = []llvm.Value{callback, next}
for _, param := range instr.Call.Args { for _, param := range instr.Call.Args {
llvmParam := c.getValue(frame, param) llvmParam := frame.getValue(param)
values = append(values, llvmParam) values = append(values, llvmParam)
valueTypes = append(valueTypes, llvmParam.Type()) valueTypes = append(valueTypes, llvmParam.Type())
} }

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

@ -20,7 +20,7 @@ func (c *compilerContext) makeError(pos token.Pos, msg string) types.Error {
} }
} }
func (c *Compiler) addError(pos token.Pos, msg string) { func (c *compilerContext) addError(pos token.Pos, msg string) {
c.diagnostics = append(c.diagnostics, c.makeError(pos, msg)) c.diagnostics = append(c.diagnostics, c.makeError(pos, msg))
} }

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

@ -14,6 +14,18 @@ import (
// createFuncValue creates a function value from a raw function pointer with no // createFuncValue creates a function value from a raw function pointer with no
// context. // context.
func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value { func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
return c.compilerContext.createFuncValue(c.builder, funcPtr, context, sig)
}
// createFuncValue creates a function value from a raw function pointer with no
// context.
func (b *builder) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
return b.compilerContext.createFuncValue(b.Builder, funcPtr, context, sig)
}
// createFuncValue creates a function value from a raw function pointer with no
// context.
func (c *compilerContext) createFuncValue(builder llvm.Builder, funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
var funcValueScalar llvm.Value var funcValueScalar llvm.Value
switch c.FuncImplementation() { switch c.FuncImplementation() {
case compileopts.FuncValueDoubleword: case compileopts.FuncValueDoubleword:
@ -40,8 +52,8 @@ func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signa
} }
funcValueType := c.getFuncType(sig) funcValueType := c.getFuncType(sig)
funcValue := llvm.Undef(funcValueType) funcValue := llvm.Undef(funcValueType)
funcValue = c.builder.CreateInsertValue(funcValue, context, 0, "") funcValue = builder.CreateInsertValue(funcValue, context, 0, "")
funcValue = c.builder.CreateInsertValue(funcValue, funcValueScalar, 1, "") funcValue = builder.CreateInsertValue(funcValue, funcValueScalar, 1, "")
return funcValue return funcValue
} }
@ -151,7 +163,7 @@ func (c *Compiler) parseMakeClosure(frame *Frame, expr *ssa.MakeClosure) (llvm.V
boundVars := make([]llvm.Value, len(expr.Bindings)) boundVars := make([]llvm.Value, len(expr.Bindings))
for i, binding := range expr.Bindings { for i, binding := range expr.Bindings {
// The context stores the bound variables. // The context stores the bound variables.
llvmBoundVar := c.getValue(frame, binding) llvmBoundVar := frame.getValue(binding)
boundVars[i] = llvmBoundVar boundVars[i] = llvmBoundVar
} }

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

@ -77,7 +77,7 @@ func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value,
} }
key := constant.StringVal(r.Key.(*ssa.Const).Value) key := constant.StringVal(r.Key.(*ssa.Const).Value)
//println("value:", r.Value.(*ssa.MakeInterface).X.String()) //println("value:", r.Value.(*ssa.MakeInterface).X.String())
registers[key] = c.getValue(frame, r.Value.(*ssa.MakeInterface).X) registers[key] = frame.getValue(r.Value.(*ssa.MakeInterface).X)
case *ssa.Call: case *ssa.Call:
if r.Common() == instr { if r.Common() == instr {
break break
@ -150,7 +150,7 @@ func (c *Compiler) emitSVCall(frame *Frame, args []ssa.Value) (llvm.Value, error
} else { } else {
constraints += ",{r" + strconv.Itoa(i) + "}" constraints += ",{r" + strconv.Itoa(i) + "}"
} }
llvmValue := c.getValue(frame, arg) llvmValue := frame.getValue(arg)
llvmArgs = append(llvmArgs, llvmValue) llvmArgs = append(llvmArgs, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }
@ -190,19 +190,19 @@ func (c *Compiler) emitCSROperation(frame *Frame, call *ssa.CallCommon) (llvm.Va
fnType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.uintptrType}, false) fnType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.uintptrType}, false)
asm := fmt.Sprintf("csrw %d, $0", csr) asm := fmt.Sprintf("csrw %d, $0", csr)
target := llvm.InlineAsm(fnType, asm, "r", true, false, 0) target := llvm.InlineAsm(fnType, asm, "r", true, false, 0)
return c.builder.CreateCall(target, []llvm.Value{c.getValue(frame, call.Args[1])}, ""), nil return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
case "SetBits": case "SetBits":
// Note: it may be possible to optimize this to csrrsi in many cases. // 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(c.uintptrType, []llvm.Type{c.uintptrType}, false)
asm := fmt.Sprintf("csrrs $0, %d, $1", csr) asm := fmt.Sprintf("csrrs $0, %d, $1", csr)
target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0) target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0)
return c.builder.CreateCall(target, []llvm.Value{c.getValue(frame, call.Args[1])}, ""), nil return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
case "ClearBits": case "ClearBits":
// Note: it may be possible to optimize this to csrrci in many cases. // 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(c.uintptrType, []llvm.Type{c.uintptrType}, false)
asm := fmt.Sprintf("csrrc $0, %d, $1", csr) asm := fmt.Sprintf("csrrc $0, %d, $1", csr)
target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0) target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0)
return c.builder.CreateCall(target, []llvm.Value{c.getValue(frame, call.Args[1])}, ""), nil return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
default: default:
return llvm.Value{}, c.makeError(call.Pos(), "unknown CSR operation: "+name) return llvm.Value{}, c.makeError(call.Pos(), "unknown CSR operation: "+name)
} }

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

@ -44,7 +44,7 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, pos token.
// getTypeCode returns a reference to a type code. // getTypeCode returns a reference to a type code.
// It returns a pointer to an external global which should be replaced with the // It returns a pointer to an external global which should be replaced with the
// real type in the interface lowering pass. // real type in the interface lowering pass.
func (c *Compiler) getTypeCode(typ types.Type) llvm.Value { func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
globalName := "reflect/types.type:" + getTypeCodeName(typ) globalName := "reflect/types.type:" + getTypeCodeName(typ)
global := c.mod.NamedGlobal(globalName) global := c.mod.NamedGlobal(globalName)
if global.IsNil() { if global.IsNil() {
@ -91,7 +91,7 @@ func (c *Compiler) getTypeCode(typ types.Type) llvm.Value {
// makeStructTypeFields creates a new global that stores all type information // makeStructTypeFields creates a new global that stores all type information
// related to this struct type, and returns the resulting global. This global is // related to this struct type, and returns the resulting global. This global is
// actually an array of all the fields in the structs. // actually an array of all the fields in the structs.
func (c *Compiler) makeStructTypeFields(typ *types.Struct) llvm.Value { func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value {
// The global is an array of runtime.structField structs. // The global is an array of runtime.structField structs.
runtimeStructField := c.getLLVMRuntimeType("structField") runtimeStructField := c.getLLVMRuntimeType("structField")
structGlobalType := llvm.ArrayType(runtimeStructField, typ.NumFields()) structGlobalType := llvm.ArrayType(runtimeStructField, typ.NumFields())
@ -315,7 +315,7 @@ func (c *Compiler) getMethodSignature(method *types.Func) llvm.Value {
// Type asserts on concrete types are trivial: just compare type numbers. Type // Type asserts on concrete types are trivial: just compare type numbers. Type
// asserts on interfaces are more difficult, see the comments in the function. // asserts on interfaces are more difficult, see the comments in the function.
func (c *Compiler) parseTypeAssert(frame *Frame, expr *ssa.TypeAssert) llvm.Value { func (c *Compiler) parseTypeAssert(frame *Frame, expr *ssa.TypeAssert) llvm.Value {
itf := c.getValue(frame, expr.X) itf := frame.getValue(expr.X)
assertedType := c.getLLVMType(expr.AssertedType) assertedType := c.getLLVMType(expr.AssertedType)
actualTypeNum := c.builder.CreateExtractValue(itf, 0, "interface.type") actualTypeNum := c.builder.CreateExtractValue(itf, 0, "interface.type")
@ -395,7 +395,7 @@ func (c *Compiler) parseTypeAssert(frame *Frame, expr *ssa.TypeAssert) llvm.Valu
// interface call. It can be used in a call or defer instruction. // interface call. It can be used in a call or defer instruction.
func (c *Compiler) getInvokeCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, []llvm.Value) { func (c *Compiler) getInvokeCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, []llvm.Value) {
// Call an interface method with dynamic dispatch. // Call an interface method with dynamic dispatch.
itf := c.getValue(frame, instr.Value) // interface itf := frame.getValue(instr.Value) // interface
llvmFnType := c.getRawFuncType(instr.Method.Type().(*types.Signature)) llvmFnType := c.getRawFuncType(instr.Method.Type().(*types.Signature))
@ -411,7 +411,7 @@ func (c *Compiler) getInvokeCall(frame *Frame, instr *ssa.CallCommon) (llvm.Valu
args := []llvm.Value{receiverValue} args := []llvm.Value{receiverValue}
for _, arg := range instr.Args { for _, arg := range instr.Args {
args = append(args, c.getValue(frame, arg)) args = append(args, frame.getValue(arg))
} }
// Add the context parameter. An interface call never takes a context but we // Add the context parameter. An interface call never takes a context but we
// have to supply the parameter anyway. // have to supply the parameter anyway.

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

@ -24,7 +24,7 @@ func (c *Compiler) emitInterruptGlobal(frame *Frame, instr *ssa.CallCommon) (llv
// Note that bound functions are allowed if the function has a pointer // Note that bound functions are allowed if the function has a pointer
// receiver and is a global. This is rather strict but still allows for // receiver and is a global. This is rather strict but still allows for
// idiomatic Go code. // idiomatic Go code.
funcValue := c.getValue(frame, instr.Args[1]) funcValue := frame.getValue(instr.Args[1])
if funcValue.IsAConstant().IsNil() { if funcValue.IsAConstant().IsNil() {
// Try to determine the cause of the non-constantness for a nice error // Try to determine the cause of the non-constantness for a nice error
// message. // message.

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

@ -56,7 +56,7 @@ func (c *Compiler) emitPointerUnpack(ptr llvm.Value, valueTypes []llvm.Type) []l
// contents, and returns the global. // contents, and returns the global.
// Note that it is left with the default linkage etc., you should set // Note that it is left with the default linkage etc., you should set
// linkage/constant/etc properties yourself. // linkage/constant/etc properties yourself.
func (c *Compiler) makeGlobalArray(buf []byte, name string, elementType llvm.Type) llvm.Value { func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType llvm.Type) llvm.Value {
globalType := llvm.ArrayType(elementType, len(buf)) globalType := llvm.ArrayType(elementType, len(buf))
global := llvm.AddGlobal(c.mod, globalType, name) global := llvm.AddGlobal(c.mod, globalType, name)
value := llvm.Undef(globalType) value := llvm.Undef(globalType)

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

@ -34,7 +34,7 @@ func (c *Compiler) emitMakeMap(frame *Frame, expr *ssa.MakeMap) (llvm.Value, err
llvmValueSize := llvm.ConstInt(c.ctx.Int8Type(), valueSize, false) llvmValueSize := llvm.ConstInt(c.ctx.Int8Type(), valueSize, false)
sizeHint := llvm.ConstInt(c.uintptrType, 8, false) sizeHint := llvm.ConstInt(c.uintptrType, 8, false)
if expr.Reserve != nil { if expr.Reserve != nil {
sizeHint = c.getValue(frame, expr.Reserve) sizeHint = frame.getValue(expr.Reserve)
var err error var err error
sizeHint, err = c.parseConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos()) sizeHint, err = c.parseConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos())
if err != nil { if err != nil {

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

@ -56,7 +56,7 @@ func (c *Compiler) loadASTComments(lprogram *loader.Program) {
// getGlobal returns a LLVM IR global value for a Go SSA global. It is added to // getGlobal returns a LLVM IR global value for a Go SSA global. It is added to
// the LLVM IR if it has not been added already. // the LLVM IR if it has not been added already.
func (c *Compiler) getGlobal(g *ssa.Global) llvm.Value { func (c *compilerContext) getGlobal(g *ssa.Global) llvm.Value {
info := c.getGlobalInfo(g) info := c.getGlobalInfo(g)
llvmGlobal := c.mod.NamedGlobal(info.linkName) llvmGlobal := c.mod.NamedGlobal(info.linkName)
if llvmGlobal.IsNil() { if llvmGlobal.IsNil() {
@ -104,7 +104,7 @@ func (c *Compiler) getGlobal(g *ssa.Global) llvm.Value {
} }
// getGlobalInfo returns some information about a specific global. // getGlobalInfo returns some information about a specific global.
func (c *Compiler) getGlobalInfo(g *ssa.Global) globalInfo { func (c *compilerContext) getGlobalInfo(g *ssa.Global) globalInfo {
info := globalInfo{} info := globalInfo{}
if strings.HasPrefix(g.Name(), "C.") { if strings.HasPrefix(g.Name(), "C.") {
// Created by CGo: such a name cannot be created by regular C code. // Created by CGo: such a name cannot be created by regular C code.

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

@ -13,7 +13,7 @@ import (
// emitSyscall emits an inline system call instruction, depending on the target // emitSyscall emits an inline system call instruction, depending on the target
// OS/arch. // OS/arch.
func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value, error) { func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value, error) {
num := c.getValue(frame, call.Args[0]) num := frame.getValue(call.Args[0])
var syscallResult llvm.Value var syscallResult llvm.Value
switch { switch {
case c.GOARCH() == "amd64": case c.GOARCH() == "amd64":
@ -50,7 +50,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
"{r12}", "{r12}",
"{r13}", "{r13}",
}[i] }[i]
llvmValue := c.getValue(frame, arg) llvmValue := frame.getValue(arg)
args = append(args, llvmValue) args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }
@ -77,7 +77,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
"{edi}", "{edi}",
"{ebp}", "{ebp}",
}[i] }[i]
llvmValue := c.getValue(frame, arg) llvmValue := frame.getValue(arg)
args = append(args, llvmValue) args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }
@ -102,7 +102,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
"{r5}", "{r5}",
"{r6}", "{r6}",
}[i] }[i]
llvmValue := c.getValue(frame, arg) llvmValue := frame.getValue(arg)
args = append(args, llvmValue) args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }
@ -132,7 +132,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
"{x4}", "{x4}",
"{x5}", "{x5}",
}[i] }[i]
llvmValue := c.getValue(frame, arg) llvmValue := frame.getValue(arg)
args = append(args, llvmValue) args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }

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

@ -9,7 +9,7 @@ import (
) )
func (c *Compiler) emitVolatileLoad(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) { func (c *Compiler) emitVolatileLoad(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) {
addr := c.getValue(frame, instr.Args[0]) addr := frame.getValue(instr.Args[0])
c.emitNilCheck(frame, addr, "deref") c.emitNilCheck(frame, addr, "deref")
val := c.builder.CreateLoad(addr, "") val := c.builder.CreateLoad(addr, "")
val.SetVolatile(true) val.SetVolatile(true)
@ -17,8 +17,8 @@ func (c *Compiler) emitVolatileLoad(frame *Frame, instr *ssa.CallCommon) (llvm.V
} }
func (c *Compiler) emitVolatileStore(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) { func (c *Compiler) emitVolatileStore(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) {
addr := c.getValue(frame, instr.Args[0]) addr := frame.getValue(instr.Args[0])
val := c.getValue(frame, instr.Args[1]) val := frame.getValue(instr.Args[1])
c.emitNilCheck(frame, addr, "deref") c.emitNilCheck(frame, addr, "deref")
store := c.builder.CreateStore(val, addr) store := c.builder.CreateStore(val, addr)
store.SetVolatile(true) store.SetVolatile(true)