From 349ecf17361afc3ab1e4d7d051fd5fa9adf34665 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 23 Nov 2019 00:01:20 +0100 Subject: [PATCH] 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. --- compiler/channel.go | 18 +++--- compiler/compiler.go | 138 +++++++++++++++++++++--------------------- compiler/defer.go | 10 +-- compiler/errors.go | 2 +- compiler/func.go | 18 +++++- compiler/inlineasm.go | 10 +-- compiler/interface.go | 10 +-- compiler/interrupt.go | 2 +- compiler/llvm.go | 2 +- compiler/map.go | 2 +- compiler/symbol.go | 4 +- compiler/syscall.go | 10 +-- compiler/volatile.go | 6 +- 13 files changed, 122 insertions(+), 110 deletions(-) diff --git a/compiler/channel.go b/compiler/channel.go index de7b12e2..bdfdf9b9 100644 --- a/compiler/channel.go +++ b/compiler/channel.go @@ -14,7 +14,7 @@ import ( func (c *Compiler) emitMakeChan(frame *Frame, expr *ssa.MakeChan) llvm.Value { elementSize := c.targetData.TypeAllocSize(c.getLLVMType(expr.Type().(*types.Chan).Elem())) 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()) if bufSize.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { 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 // channel send operation during goroutine lowering. func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) { - ch := c.getValue(frame, instr.Chan) - chanValue := c.getValue(frame, instr.X) + ch := frame.getValue(instr.Chan) + chanValue := frame.getValue(instr.X) // store value-to-send 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. func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) llvm.Value { 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. 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. func (c *Compiler) emitChanClose(frame *Frame, param ssa.Value) { - ch := c.getValue(frame, param) + ch := frame.getValue(param) 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 chanSelectStateType := c.getLLVMRuntimeType("chanSelectState") for _, state := range expr.States { - ch := c.getValue(frame, state.Chan) + ch := frame.getValue(state.Chan) selectState := llvm.ConstNull(chanSelectStateType) selectState = c.builder.CreateInsertValue(selectState, ch, 0, "") switch state.Dir { @@ -128,7 +128,7 @@ func (c *Compiler) emitSelect(frame *Frame, expr *ssa.Select) llvm.Value { case types.SendOnly: // Store this value in an alloca and put a pointer to this alloca // 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") c.builder.CreateStore(sendValue, alloca) 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 { if expr.Index == 0 { // index - value := c.getValue(frame, expr.Tuple) + value := frame.getValue(expr.Tuple) index := c.builder.CreateExtractValue(value, expr.Index, "") if index.Type().IntTypeWidth() < c.intType.IntTypeWidth() { index = c.builder.CreateSExt(index, c.intType, "") @@ -227,7 +227,7 @@ func (c *Compiler) getChanSelectResult(frame *Frame, expr *ssa.Extract) llvm.Val return index } else if expr.Index == 1 { // comma-ok - value := c.getValue(frame, expr.Tuple) + value := frame.getValue(expr.Tuple) return c.builder.CreateExtractValue(value, expr.Index, "") } else { // Select statements are (index, ok, ...) where ... is a number of diff --git a/compiler/compiler.go b/compiler/compiler.go index 05540ab6..db2ca66f 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -53,6 +53,7 @@ type compilerContext struct { uintptrType llvm.Type ir *ir.Program diagnostics []error + astComments map[string]*ast.CommentGroup } type Compiler struct { @@ -60,7 +61,6 @@ type Compiler struct { builder llvm.Builder initFuncs []llvm.Value interfaceInvokeWrappers []interfaceInvokeWrapper - astComments map[string]*ast.CommentGroup } type Frame struct { @@ -513,7 +513,7 @@ func isPointer(typ types.Type) bool { } // 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 { 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, // 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) sizeInBytes := c.targetData.TypeAllocSize(llvmType) 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 // use one that was already created, otherwise it falls back to creating a new // one. -func (c *Compiler) getDIFile(filename string) llvm.Metadata { +func (c *compilerContext) getDIFile(filename string) llvm.Metadata { if _, ok := c.difiles[filename]; !ok { dir, file := filepath.Split(filename) if dir != "" { @@ -988,7 +988,7 @@ func (c *Compiler) parseFunc(frame *Frame) { } dbgVar := c.getLocalVariable(frame, variable) 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), Col: uint(pos.Column), Scope: frame.difunc, @@ -1013,7 +1013,7 @@ func (c *Compiler) parseFunc(frame *Frame) { for _, phi := range frame.phis { block := phi.ssa.Block() for i, edge := range phi.ssa.Edges { - llvmVal := c.getValue(frame, edge) + llvmVal := frame.getValue(edge) llvmBlock := frame.blockExits[block.Preds[i]] 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. var params []llvm.Value for _, param := range instr.Call.Args { - params = append(params, c.getValue(frame, param)) + params = append(params, frame.getValue(param)) } // Start a new goroutine. @@ -1067,7 +1067,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) { case *ssa.MakeClosure: // A goroutine call on a func value, but the callee is trivial to find. For // example: immediately applied functions. - funcValue := c.getValue(frame, value) + funcValue := frame.getValue(value) context = c.extractFuncContext(funcValue) default: panic("StaticCallee returned an unexpected value") @@ -1080,7 +1080,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) { // goroutine: // * The function context, for closures. // * 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 switch c.Scheduler() { 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") } case *ssa.If: - cond := c.getValue(frame, instr.Cond) + cond := frame.getValue(instr.Cond) block := instr.Block() blockThen := frame.blockEntries[block.Succs[0]] 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]] c.builder.CreateBr(blockJump) case *ssa.MapUpdate: - m := c.getValue(frame, instr.Map) - key := c.getValue(frame, instr.Key) - value := c.getValue(frame, instr.Value) + m := frame.getValue(instr.Map) + key := frame.getValue(instr.Key) + value := frame.getValue(instr.Value) mapType := instr.Map.Type().Underlying().(*types.Map) c.emitMapUpdate(mapType.Key(), m, key, value, instr.Pos()) case *ssa.Panic: - value := c.getValue(frame, instr.X) + value := frame.getValue(instr.X) c.createRuntimeCall("_panic", []llvm.Value{value}, "") c.builder.CreateUnreachable() case *ssa.Return: if len(instr.Results) == 0 { c.builder.CreateRetVoid() } else if len(instr.Results) == 1 { - c.builder.CreateRet(c.getValue(frame, instr.Results[0])) + c.builder.CreateRet(frame.getValue(instr.Results[0])) } else { // Multiple return values. Put them all in a struct. retVal := llvm.ConstNull(frame.fn.LLVMFn.Type().ElementType().ReturnType()) for i, result := range instr.Results { - val := c.getValue(frame, result) + val := frame.getValue(result) retVal = c.builder.CreateInsertValue(retVal, val, i, "") } c.builder.CreateRet(retVal) @@ -1133,8 +1133,8 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) { case *ssa.Send: c.emitChanSend(frame, instr) case *ssa.Store: - llvmAddr := c.getValue(frame, instr.Addr) - llvmVal := c.getValue(frame, instr.Val) + llvmAddr := frame.getValue(instr.Addr) + llvmVal := frame.getValue(instr.Val) c.emitNilCheck(frame, llvmAddr, "store") if c.targetData.TypeAllocSize(llvmVal.Type()) == 0 { // 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) { switch callName { case "append": - src := c.getValue(frame, args[0]) - elems := c.getValue(frame, args[1]) + src := frame.getValue(args[0]) + elems := frame.getValue(args[1]) srcBuf := c.builder.CreateExtractValue(src, 0, "append.srcBuf") srcPtr := c.builder.CreateBitCast(srcBuf, c.i8ptrType, "append.srcPtr") 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, "") return newSlice, nil case "cap": - value := c.getValue(frame, args[0]) + value := frame.getValue(args[0]) var llvmCap llvm.Value switch args[0].Type().(type) { case *types.Chan: @@ -1191,8 +1191,8 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string, c.emitChanClose(frame, args[0]) return llvm.Value{}, nil case "complex": - r := c.getValue(frame, args[0]) - i := c.getValue(frame, args[1]) + r := frame.getValue(args[0]) + i := frame.getValue(args[1]) t := args[0].Type().Underlying().(*types.Basic) var cplx llvm.Value 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, "") return cplx, nil case "copy": - dst := c.getValue(frame, args[0]) - src := c.getValue(frame, args[1]) + dst := frame.getValue(args[0]) + src := frame.getValue(args[1]) dstLen := c.builder.CreateExtractValue(dst, 1, "copy.dstLen") srcLen := c.builder.CreateExtractValue(src, 1, "copy.srcLen") 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) return c.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil case "delete": - m := c.getValue(frame, args[0]) - key := c.getValue(frame, args[1]) + m := frame.getValue(args[0]) + key := frame.getValue(args[1]) return llvm.Value{}, c.emitMapDelete(args[1].Type(), m, key, pos) case "imag": - cplx := c.getValue(frame, args[0]) + cplx := frame.getValue(args[0]) return c.builder.CreateExtractValue(cplx, 1, "imag"), nil case "len": - value := c.getValue(frame, args[0]) + value := frame.getValue(args[0]) var llvmLen llvm.Value switch args[0].Type().Underlying().(type) { 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" { c.createRuntimeCall("printspace", nil, "") } - value := c.getValue(frame, arg) + value := frame.getValue(arg) typ := arg.Type().Underlying() switch typ := typ.(type) { 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 case "real": - cplx := c.getValue(frame, args[0]) + cplx := frame.getValue(args[0]) return c.builder.CreateExtractValue(cplx, 0, "real"), nil case "recover": return c.createRuntimeCall("_recover", nil, ""), nil case "ssa:wrapnilchk": // TODO: do an actual nil check? - return c.getValue(frame, args[0]), nil + return frame.getValue(args[0]), nil default: 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 { var params []llvm.Value for _, param := range args { - params = append(params, c.getValue(frame, param)) + params = append(params, frame.getValue(param)) } if !exported { @@ -1375,7 +1375,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e case *ssa.MakeClosure: // A call on a func value, but the callee is trivial to find. For // example: immediately applied functions. - funcValue := c.getValue(frame, value) + funcValue := frame.getValue(value) context = c.extractFuncContext(funcValue) default: 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: return c.parseBuiltin(frame, instr.Args, call.Name(), instr.Pos()) 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 // extract the function pointer and context first from the func value. 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 // 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) { case *ssa.Const: - return frame.createConst(frame.fn.LinkName(), expr) + return b.createConst(b.fn.LinkName(), expr) case *ssa.Function: - fn := c.ir.GetFunction(expr) + fn := b.ir.GetFunction(expr) if fn.IsExported() { - c.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String()) - return llvm.Undef(c.getLLVMType(expr.Type())) + b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String()) + 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: - value := c.getGlobal(expr) + value := b.getGlobal(expr) if value.IsNil() { - c.addError(expr.Pos(), "global not found: "+expr.RelString(nil)) - return llvm.Undef(c.getLLVMType(expr.Type())) + b.addError(expr.Pos(), "global not found: "+expr.RelString(nil)) + return llvm.Undef(b.getLLVMType(expr.Type())) } return value default: // other (local) SSA value - if value, ok := frame.locals[expr]; ok { + if value, ok := b.locals[expr]; ok { return value } else { // indicates a compiler bug @@ -1458,8 +1458,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { return buf, nil } case *ssa.BinOp: - x := c.getValue(frame, expr.X) - y := c.getValue(frame, expr.Y) + x := frame.getValue(expr.X) + y := frame.getValue(expr.Y) return frame.createBinOp(expr.Op, expr.X.Type(), x, y, expr.Pos()) case *ssa.Call: // 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 // heap allocation and because it's easier to implement, see: // https://research.swtch.com/interfaces - return c.getValue(frame, expr.X), nil + return frame.getValue(expr.X), nil case *ssa.ChangeType: // 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 // LLVM type as well. - x := c.getValue(frame, expr.X) + x := frame.getValue(expr.X) llvmType := c.getLLVMType(expr.Type()) if x.Type() == llvmType { // 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: panic("const is not an expression") 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()) case *ssa.Extract: if _, ok := expr.Tuple.(*ssa.Select); ok { 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 case *ssa.Field: - value := c.getValue(frame, expr.X) + value := frame.getValue(expr.X) result := c.builder.CreateExtractValue(value, expr.Field, "") return result, nil 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: // > 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 @@ -1536,8 +1536,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { case *ssa.Global: panic("global is not an expression") case *ssa.Index: - array := c.getValue(frame, expr.X) - index := c.getValue(frame, expr.Index) + array := frame.getValue(expr.X) + index := frame.getValue(expr.Index) // Check bounds. 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) return result, nil case *ssa.IndexAddr: - val := c.getValue(frame, expr.X) - index := c.getValue(frame, expr.Index) + val := frame.getValue(expr.X) + index := frame.getValue(expr.Index) // Get buffer pointer and length var bufptr, buflen llvm.Value @@ -1599,8 +1599,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { panic("unreachable") } case *ssa.Lookup: - value := c.getValue(frame, expr.X) - index := c.getValue(frame, expr.Index) + value := frame.getValue(expr.X) + index := frame.getValue(expr.Index) switch xType := expr.X.Type().Underlying().(type) { case *types.Basic: // 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: return c.parseMakeClosure(frame, expr) case *ssa.MakeInterface: - val := c.getValue(frame, expr.X) + val := frame.getValue(expr.X) return c.parseMakeInterface(val, expr.X.Type(), expr.Pos()), nil case *ssa.MakeMap: return c.emitMakeMap(frame, expr) case *ssa.MakeSlice: - sliceLen := c.getValue(frame, expr.Len) - sliceCap := c.getValue(frame, expr.Cap) + sliceLen := frame.getValue(expr.Len) + sliceCap := frame.getValue(expr.Cap) sliceType := expr.Type().Underlying().(*types.Slice) llvmElemType := c.getLLVMType(sliceType.Elem()) elemSize := c.targetData.TypeAllocSize(llvmElemType) @@ -1688,8 +1688,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { return slice, nil case *ssa.Next: rangeVal := expr.Iter.(*ssa.Range).X - llvmRangeVal := c.getValue(frame, rangeVal) - it := c.getValue(frame, expr.Iter) + llvmRangeVal := frame.getValue(rangeVal) + it := frame.getValue(expr.Iter) if expr.IsString { return c.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil } else { // map @@ -1728,14 +1728,14 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { case *ssa.Select: return c.emitSelect(frame, expr), nil case *ssa.Slice: - value := c.getValue(frame, expr.X) + value := frame.getValue(expr.X) var lowType, highType, maxType *types.Basic var low, high, max llvm.Value if expr.Low != nil { 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 lowType.Info()&types.IsUnsigned != 0 { 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 { 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 highType.Info()&types.IsUnsigned != 0 { 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 { 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 maxType.Info()&types.IsUnsigned != 0 { 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) { - x := c.getValue(frame, unop.X) + x := frame.getValue(unop.X) switch unop.Op { case token.NOT: // !x return c.builder.CreateNot(x, ""), nil diff --git a/compiler/defer.go b/compiler/defer.go index bc826032..a2d878a4 100644 --- a/compiler/defer.go +++ b/compiler/defer.go @@ -91,12 +91,12 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) { // Collect all values to be put in the struct (starting with // 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") values = []llvm.Value{callback, next, receiverValue} valueTypes = append(valueTypes, c.i8ptrType) for _, arg := range instr.Call.Args { - val := c.getValue(frame, arg) + val := frame.getValue(arg) values = append(values, val) valueTypes = append(valueTypes, val.Type()) } @@ -115,7 +115,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) { // runtime._defer fields). values = []llvm.Value{callback, next} for _, param := range instr.Call.Args { - llvmParam := c.getValue(frame, param) + llvmParam := frame.getValue(param) values = append(values, llvmParam) valueTypes = append(valueTypes, llvmParam.Type()) } @@ -127,7 +127,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) { // pointer. // TODO: ignore this closure entirely and put pointers to the free // 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, "") // Get the callback number. @@ -143,7 +143,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) { // context pointer). values = []llvm.Value{callback, next} for _, param := range instr.Call.Args { - llvmParam := c.getValue(frame, param) + llvmParam := frame.getValue(param) values = append(values, llvmParam) valueTypes = append(valueTypes, llvmParam.Type()) } diff --git a/compiler/errors.go b/compiler/errors.go index 37205f01..85de4d16 100644 --- a/compiler/errors.go +++ b/compiler/errors.go @@ -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)) } diff --git a/compiler/func.go b/compiler/func.go index c64c52c9..69fb78bc 100644 --- a/compiler/func.go +++ b/compiler/func.go @@ -14,6 +14,18 @@ import ( // createFuncValue creates a function value from a raw function pointer with no // context. 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 switch c.FuncImplementation() { case compileopts.FuncValueDoubleword: @@ -40,8 +52,8 @@ func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signa } funcValueType := c.getFuncType(sig) funcValue := llvm.Undef(funcValueType) - funcValue = c.builder.CreateInsertValue(funcValue, context, 0, "") - funcValue = c.builder.CreateInsertValue(funcValue, funcValueScalar, 1, "") + funcValue = builder.CreateInsertValue(funcValue, context, 0, "") + funcValue = builder.CreateInsertValue(funcValue, funcValueScalar, 1, "") return funcValue } @@ -151,7 +163,7 @@ func (c *Compiler) parseMakeClosure(frame *Frame, expr *ssa.MakeClosure) (llvm.V boundVars := make([]llvm.Value, len(expr.Bindings)) for i, binding := range expr.Bindings { // The context stores the bound variables. - llvmBoundVar := c.getValue(frame, binding) + llvmBoundVar := frame.getValue(binding) boundVars[i] = llvmBoundVar } diff --git a/compiler/inlineasm.go b/compiler/inlineasm.go index e9f093a7..77e1af96 100644 --- a/compiler/inlineasm.go +++ b/compiler/inlineasm.go @@ -77,7 +77,7 @@ func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value, } key := constant.StringVal(r.Key.(*ssa.Const).Value) //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: if r.Common() == instr { break @@ -150,7 +150,7 @@ func (c *Compiler) emitSVCall(frame *Frame, args []ssa.Value) (llvm.Value, error } else { constraints += ",{r" + strconv.Itoa(i) + "}" } - llvmValue := c.getValue(frame, arg) + llvmValue := frame.getValue(arg) llvmArgs = append(llvmArgs, llvmValue) 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) asm := fmt.Sprintf("csrw %d, $0", csr) 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": // Note: it may be possible to optimize this to csrrsi in many cases. fnType := llvm.FunctionType(c.uintptrType, []llvm.Type{c.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{c.getValue(frame, call.Args[1])}, ""), nil + return c.builder.CreateCall(target, []llvm.Value{frame.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) 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{c.getValue(frame, call.Args[1])}, ""), nil + return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil default: return llvm.Value{}, c.makeError(call.Pos(), "unknown CSR operation: "+name) } diff --git a/compiler/interface.go b/compiler/interface.go index f1599cd2..7904df72 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -44,7 +44,7 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, pos token. // getTypeCode returns a reference to a type code. // It returns a pointer to an external global which should be replaced with the // 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) global := c.mod.NamedGlobal(globalName) 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 // related to this struct type, and returns the resulting global. This global is // 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. runtimeStructField := c.getLLVMRuntimeType("structField") 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 // asserts on interfaces are more difficult, see the comments in the function. 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) 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. func (c *Compiler) getInvokeCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, []llvm.Value) { // 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)) @@ -411,7 +411,7 @@ func (c *Compiler) getInvokeCall(frame *Frame, instr *ssa.CallCommon) (llvm.Valu args := []llvm.Value{receiverValue} 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 // have to supply the parameter anyway. diff --git a/compiler/interrupt.go b/compiler/interrupt.go index 67cb8eca..7f4fd77a 100644 --- a/compiler/interrupt.go +++ b/compiler/interrupt.go @@ -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 // receiver and is a global. This is rather strict but still allows for // idiomatic Go code. - funcValue := c.getValue(frame, instr.Args[1]) + funcValue := frame.getValue(instr.Args[1]) if funcValue.IsAConstant().IsNil() { // Try to determine the cause of the non-constantness for a nice error // message. diff --git a/compiler/llvm.go b/compiler/llvm.go index 53d52bba..ff2b4c60 100644 --- a/compiler/llvm.go +++ b/compiler/llvm.go @@ -56,7 +56,7 @@ func (c *Compiler) emitPointerUnpack(ptr llvm.Value, valueTypes []llvm.Type) []l // contents, and returns the global. // Note that it is left with the default linkage etc., you should set // 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)) global := llvm.AddGlobal(c.mod, globalType, name) value := llvm.Undef(globalType) diff --git a/compiler/map.go b/compiler/map.go index 5faf7aed..6f93b888 100644 --- a/compiler/map.go +++ b/compiler/map.go @@ -34,7 +34,7 @@ func (c *Compiler) emitMakeMap(frame *Frame, expr *ssa.MakeMap) (llvm.Value, err llvmValueSize := llvm.ConstInt(c.ctx.Int8Type(), valueSize, false) sizeHint := llvm.ConstInt(c.uintptrType, 8, false) if expr.Reserve != nil { - sizeHint = c.getValue(frame, expr.Reserve) + sizeHint = frame.getValue(expr.Reserve) var err error sizeHint, err = c.parseConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos()) if err != nil { diff --git a/compiler/symbol.go b/compiler/symbol.go index ae853f18..716fc86b 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -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 // 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) llvmGlobal := c.mod.NamedGlobal(info.linkName) if llvmGlobal.IsNil() { @@ -104,7 +104,7 @@ func (c *Compiler) getGlobal(g *ssa.Global) llvm.Value { } // 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{} if strings.HasPrefix(g.Name(), "C.") { // Created by CGo: such a name cannot be created by regular C code. diff --git a/compiler/syscall.go b/compiler/syscall.go index 8dbc8192..074a88ca 100644 --- a/compiler/syscall.go +++ b/compiler/syscall.go @@ -13,7 +13,7 @@ import ( // emitSyscall emits an inline system call instruction, depending on the target // OS/arch. 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 switch { case c.GOARCH() == "amd64": @@ -50,7 +50,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value, "{r12}", "{r13}", }[i] - llvmValue := c.getValue(frame, arg) + llvmValue := frame.getValue(arg) args = append(args, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -77,7 +77,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value, "{edi}", "{ebp}", }[i] - llvmValue := c.getValue(frame, arg) + llvmValue := frame.getValue(arg) args = append(args, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -102,7 +102,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value, "{r5}", "{r6}", }[i] - llvmValue := c.getValue(frame, arg) + llvmValue := frame.getValue(arg) args = append(args, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -132,7 +132,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value, "{x4}", "{x5}", }[i] - llvmValue := c.getValue(frame, arg) + llvmValue := frame.getValue(arg) args = append(args, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } diff --git a/compiler/volatile.go b/compiler/volatile.go index 7ee5b168..ef957d9a 100644 --- a/compiler/volatile.go +++ b/compiler/volatile.go @@ -9,7 +9,7 @@ import ( ) 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") val := c.builder.CreateLoad(addr, "") 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) { - addr := c.getValue(frame, instr.Args[0]) - val := c.getValue(frame, instr.Args[1]) + addr := frame.getValue(instr.Args[0]) + val := frame.getValue(instr.Args[1]) c.emitNilCheck(frame, addr, "deref") store := c.builder.CreateStore(val, addr) store.SetVolatile(true)