diff --git a/compiler/atomic.go b/compiler/atomic.go index 73761be4..48a9fb2d 100644 --- a/compiler/atomic.go +++ b/compiler/atomic.go @@ -13,8 +13,8 @@ import ( func (b *builder) createAtomicOp(name string) llvm.Value { switch name { case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr": - ptr := b.getValue(b.fn.Params[0]) - val := b.getValue(b.fn.Params[1]) + ptr := b.getValue(b.fn.Params[0], getPos(b.fn)) + val := b.getValue(b.fn.Params[1], getPos(b.fn)) if strings.HasPrefix(b.Triple, "avr") { // AtomicRMW does not work on AVR as intended: // - There are some register allocation issues (fixed by https://reviews.llvm.org/D97127 which is not yet in a usable LLVM release) @@ -33,8 +33,8 @@ func (b *builder) createAtomicOp(name string) llvm.Value { // Return the new value, not the original value returned by atomicrmw. return b.CreateAdd(oldVal, val, "") case "SwapInt32", "SwapInt64", "SwapUint32", "SwapUint64", "SwapUintptr", "SwapPointer": - ptr := b.getValue(b.fn.Params[0]) - val := b.getValue(b.fn.Params[1]) + ptr := b.getValue(b.fn.Params[0], getPos(b.fn)) + val := b.getValue(b.fn.Params[1], getPos(b.fn)) isPointer := val.Type().TypeKind() == llvm.PointerTypeKind if isPointer { // atomicrmw only supports integers, so cast to an integer. @@ -48,21 +48,21 @@ func (b *builder) createAtomicOp(name string) llvm.Value { } return oldVal case "CompareAndSwapInt32", "CompareAndSwapInt64", "CompareAndSwapUint32", "CompareAndSwapUint64", "CompareAndSwapUintptr", "CompareAndSwapPointer": - ptr := b.getValue(b.fn.Params[0]) - old := b.getValue(b.fn.Params[1]) - newVal := b.getValue(b.fn.Params[2]) + ptr := b.getValue(b.fn.Params[0], getPos(b.fn)) + old := b.getValue(b.fn.Params[1], getPos(b.fn)) + newVal := b.getValue(b.fn.Params[2], getPos(b.fn)) tuple := b.CreateAtomicCmpXchg(ptr, old, newVal, llvm.AtomicOrderingSequentiallyConsistent, llvm.AtomicOrderingSequentiallyConsistent, true) swapped := b.CreateExtractValue(tuple, 1, "") return swapped case "LoadInt32", "LoadInt64", "LoadUint32", "LoadUint64", "LoadUintptr", "LoadPointer": - ptr := b.getValue(b.fn.Params[0]) + ptr := b.getValue(b.fn.Params[0], getPos(b.fn)) val := b.CreateLoad(b.getLLVMType(b.fn.Signature.Results().At(0).Type()), ptr, "") val.SetOrdering(llvm.AtomicOrderingSequentiallyConsistent) val.SetAlignment(b.targetData.PrefTypeAlignment(val.Type())) // required return val case "StoreInt32", "StoreInt64", "StoreUint32", "StoreUint64", "StoreUintptr", "StorePointer": - ptr := b.getValue(b.fn.Params[0]) - val := b.getValue(b.fn.Params[1]) + ptr := b.getValue(b.fn.Params[0], getPos(b.fn)) + val := b.getValue(b.fn.Params[1], getPos(b.fn)) if strings.HasPrefix(b.Triple, "avr") { // SelectionDAGBuilder is currently missing the "are unaligned atomics allowed" check for stores. vType := val.Type() diff --git a/compiler/channel.go b/compiler/channel.go index 0ce9aa66..c8c10fe0 100644 --- a/compiler/channel.go +++ b/compiler/channel.go @@ -14,7 +14,7 @@ import ( func (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value { elementSize := b.targetData.TypeAllocSize(b.getLLVMType(expr.Type().Underlying().(*types.Chan).Elem())) elementSizeValue := llvm.ConstInt(b.uintptrType, elementSize, false) - bufSize := b.getValue(expr.Size) + bufSize := b.getValue(expr.Size, getPos(expr)) b.createChanBoundsCheck(elementSize, bufSize, expr.Size.Type().Underlying().(*types.Basic), expr.Pos()) if bufSize.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() { bufSize = b.CreateZExt(bufSize, b.uintptrType, "") @@ -27,8 +27,8 @@ func (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value { // createChanSend emits a pseudo chan send operation. It is lowered to the // actual channel send operation during goroutine lowering. func (b *builder) createChanSend(instr *ssa.Send) { - ch := b.getValue(instr.Chan) - chanValue := b.getValue(instr.X) + ch := b.getValue(instr.Chan, getPos(instr)) + chanValue := b.getValue(instr.X, getPos(instr)) // store value-to-send valueType := b.getLLVMType(instr.X.Type()) @@ -62,7 +62,7 @@ func (b *builder) createChanSend(instr *ssa.Send) { // actual channel receive operation during goroutine lowering. func (b *builder) createChanRecv(unop *ssa.UnOp) llvm.Value { valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Chan).Elem()) - ch := b.getValue(unop.X) + ch := b.getValue(unop.X, getPos(unop)) // Allocate memory to receive into. isZeroSize := b.targetData.TypeAllocSize(valueType) == 0 @@ -140,7 +140,7 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value { var selectStates []llvm.Value chanSelectStateType := b.getLLVMRuntimeType("chanSelectState") for _, state := range expr.States { - ch := b.getValue(state.Chan) + ch := b.getValue(state.Chan, state.Pos) selectState := llvm.ConstNull(chanSelectStateType) selectState = b.CreateInsertValue(selectState, ch, 0, "") switch state.Dir { @@ -156,7 +156,7 @@ func (b *builder) createSelect(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 := b.getValue(state.Send) + sendValue := b.getValue(state.Send, state.Pos) alloca := llvmutil.CreateEntryBlockAlloca(b.Builder, sendValue.Type(), "select.send.value") b.CreateStore(sendValue, alloca) ptr := b.CreateBitCast(alloca, b.i8ptrType, "") @@ -247,7 +247,7 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value { func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value { if expr.Index == 0 { // index - value := b.getValue(expr.Tuple) + value := b.getValue(expr.Tuple, getPos(expr)) index := b.CreateExtractValue(value, expr.Index, "") if index.Type().IntTypeWidth() < b.intType.IntTypeWidth() { index = b.CreateSExt(index, b.intType, "") @@ -255,7 +255,7 @@ func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value { return index } else if expr.Index == 1 { // comma-ok - value := b.getValue(expr.Tuple) + value := b.getValue(expr.Tuple, getPos(expr)) return b.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 ff04f1f7..214ef63c 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -1028,7 +1028,7 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global, global llvm.Valu var fileStructs []llvm.Value for _, file := range allFiles { fileStruct := llvm.ConstNull(llvmEmbedFileStructType) - name := c.createConst(ssa.NewConst(constant.MakeString(file.Name), types.Typ[types.String])) + name := c.createConst(ssa.NewConst(constant.MakeString(file.Name), types.Typ[types.String]), getPos(member)) fileStruct = c.builder.CreateInsertValue(fileStruct, name, 0, "") // "name" field if file.Hash != "" { data := c.getEmbedFileString(file) @@ -1321,7 +1321,7 @@ func (b *builder) createFunction() { } dbgVar := b.getLocalVariable(variable) pos := b.program.Fset.Position(instr.Pos()) - b.dibuilder.InsertValueAtEnd(b.getValue(instr.X), dbgVar, b.dibuilder.CreateExpression(nil), llvm.DebugLoc{ + b.dibuilder.InsertValueAtEnd(b.getValue(instr.X, getPos(instr)), dbgVar, b.dibuilder.CreateExpression(nil), llvm.DebugLoc{ Line: uint(pos.Line), Col: uint(pos.Column), Scope: b.difunc, @@ -1352,7 +1352,7 @@ func (b *builder) createFunction() { for _, phi := range b.phis { block := phi.ssa.Block() for i, edge := range phi.ssa.Edges { - llvmVal := b.getValue(edge) + llvmVal := b.getValue(edge, getPos(phi.ssa)) llvmBlock := b.blockExits[block.Preds[i]] phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock}) } @@ -1460,7 +1460,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) { // Start a new goroutine. b.createGo(instr) case *ssa.If: - cond := b.getValue(instr.Cond) + cond := b.getValue(instr.Cond, getPos(instr)) block := instr.Block() blockThen := b.blockEntries[block.Succs[0]] blockElse := b.blockEntries[block.Succs[1]] @@ -1469,13 +1469,13 @@ func (b *builder) createInstruction(instr ssa.Instruction) { blockJump := b.blockEntries[instr.Block().Succs[0]] b.CreateBr(blockJump) case *ssa.MapUpdate: - m := b.getValue(instr.Map) - key := b.getValue(instr.Key) - value := b.getValue(instr.Value) + m := b.getValue(instr.Map, getPos(instr)) + key := b.getValue(instr.Key, getPos(instr)) + value := b.getValue(instr.Value, getPos(instr)) mapType := instr.Map.Type().Underlying().(*types.Map) b.createMapUpdate(mapType.Key(), m, key, value, instr.Pos()) case *ssa.Panic: - value := b.getValue(instr.X) + value := b.getValue(instr.X, getPos(instr)) b.createRuntimeInvoke("_panic", []llvm.Value{value}, "") b.CreateUnreachable() case *ssa.Return: @@ -1485,12 +1485,12 @@ func (b *builder) createInstruction(instr ssa.Instruction) { if len(instr.Results) == 0 { b.CreateRetVoid() } else if len(instr.Results) == 1 { - b.CreateRet(b.getValue(instr.Results[0])) + b.CreateRet(b.getValue(instr.Results[0], getPos(instr))) } else { // Multiple return values. Put them all in a struct. retVal := llvm.ConstNull(b.llvmFn.GlobalValueType().ReturnType()) for i, result := range instr.Results { - val := b.getValue(result) + val := b.getValue(result, getPos(instr)) retVal = b.CreateInsertValue(retVal, val, i, "") } b.CreateRet(retVal) @@ -1500,8 +1500,8 @@ func (b *builder) createInstruction(instr ssa.Instruction) { case *ssa.Send: b.createChanSend(instr) case *ssa.Store: - llvmAddr := b.getValue(instr.Addr) - llvmVal := b.getValue(instr.Val) + llvmAddr := b.getValue(instr.Addr, getPos(instr)) + llvmVal := b.getValue(instr.Val, getPos(instr)) b.createNilCheck(instr.Addr, llvmAddr, "store") if b.targetData.TypeAllocSize(llvmVal.Type()) == 0 { // nothing to store @@ -1760,7 +1760,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) { var params []llvm.Value for _, param := range instr.Args { - params = append(params, b.getValue(param)) + params = append(params, b.getValue(param, getPos(instr))) } // Try to call the function directly for trivially static calls. @@ -1777,9 +1777,9 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull": return b.createInlineAsmFull(instr) case strings.HasPrefix(name, "device/arm.SVCall"): - return b.emitSVCall(instr.Args) + return b.emitSVCall(instr.Args, getPos(instr)) case strings.HasPrefix(name, "device/arm64.SVCall"): - return b.emitSV64Call(instr.Args) + return b.emitSV64Call(instr.Args, getPos(instr)) case strings.HasPrefix(name, "(device/riscv.CSR)."): return b.emitCSROperation(instr) case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall"): @@ -1816,7 +1816,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) case *ssa.MakeClosure: // A call on a func value, but the callee is trivial to find. For // example: immediately applied functions. - funcValue := b.getValue(value) + funcValue := b.getValue(value, getPos(value)) context = b.extractFuncContext(funcValue) default: panic("StaticCallee returned an unexpected value") @@ -1831,7 +1831,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) return b.createBuiltin(argTypes, params, call.Name(), instr.Pos()) } else if instr.IsInvoke() { // Interface method call (aka invoke call). - itf := b.getValue(instr.Value) // interface value (runtime._interface) + itf := b.getValue(instr.Value, getPos(instr)) // interface value (runtime._interface) typecode := b.CreateExtractValue(itf, 0, "invoke.func.typecode") value := b.CreateExtractValue(itf, 1, "invoke.func.value") // receiver // Prefix the params with receiver value and suffix with typecode. @@ -1842,7 +1842,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) context = llvm.Undef(b.i8ptrType) } else { // Function pointer. - value := b.getValue(instr.Value) + value := b.getValue(instr.Value, getPos(instr)) // This is a func value, which cannot be called directly. We have to // extract the function pointer and context first from the func value. calleeType, callee, context = b.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature)) @@ -1860,10 +1860,10 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) // getValue returns the LLVM value of a constant, function value, global, or // already processed SSA expression. -func (b *builder) getValue(expr ssa.Value) llvm.Value { +func (b *builder) getValue(expr ssa.Value, pos token.Pos) llvm.Value { switch expr := expr.(type) { case *ssa.Const: - return b.createConst(expr) + return b.createConst(expr, pos) case *ssa.Function: if b.getFunctionInfo(expr).exported { b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String()) @@ -1948,8 +1948,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { return buf, nil } case *ssa.BinOp: - x := b.getValue(expr.X) - y := b.getValue(expr.Y) + x := b.getValue(expr.X, getPos(expr)) + y := b.getValue(expr.Y, getPos(expr)) return b.createBinOp(expr.Op, expr.X.Type(), expr.Y.Type(), x, y, expr.Pos()) case *ssa.Call: return b.createFunctionCall(expr.Common()) @@ -1960,12 +1960,12 @@ func (b *builder) createExpr(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 b.getValue(expr.X), nil + return b.getValue(expr.X, getPos(expr)), 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 := b.getValue(expr.X) + x := b.getValue(expr.X, getPos(expr)) llvmType := b.getLLVMType(expr.Type()) if x.Type() == llvmType { // Different Go type but same LLVM type (for example, named int). @@ -1994,20 +1994,20 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { case *ssa.Const: panic("const is not an expression") case *ssa.Convert: - x := b.getValue(expr.X) + x := b.getValue(expr.X, getPos(expr)) return b.createConvert(expr.X.Type(), expr.Type(), x, expr.Pos()) case *ssa.Extract: if _, ok := expr.Tuple.(*ssa.Select); ok { return b.getChanSelectResult(expr), nil } - value := b.getValue(expr.Tuple) + value := b.getValue(expr.Tuple, getPos(expr)) return b.CreateExtractValue(value, expr.Index, ""), nil case *ssa.Field: - value := b.getValue(expr.X) + value := b.getValue(expr.X, getPos(expr)) result := b.CreateExtractValue(value, expr.Field, "") return result, nil case *ssa.FieldAddr: - val := b.getValue(expr.X) + val := b.getValue(expr.X, getPos(expr)) // 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 @@ -2025,8 +2025,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { case *ssa.Global: panic("global is not an expression") case *ssa.Index: - collection := b.getValue(expr.X) - index := b.getValue(expr.Index) + collection := b.getValue(expr.X, getPos(expr)) + index := b.getValue(expr.Index, getPos(expr)) switch xType := expr.X.Type().Underlying().(type) { case *types.Basic: // extract byte from string @@ -2075,8 +2075,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { panic("unknown *ssa.Index type") } case *ssa.IndexAddr: - val := b.getValue(expr.X) - index := b.getValue(expr.Index) + val := b.getValue(expr.X, getPos(expr)) + index := b.getValue(expr.Index, getPos(expr)) // Get buffer pointer and length var bufptr, buflen llvm.Value @@ -2127,8 +2127,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { panic("unreachable") } case *ssa.Lookup: // map lookup - value := b.getValue(expr.X) - index := b.getValue(expr.Index) + value := b.getValue(expr.X, getPos(expr)) + index := b.getValue(expr.Index, getPos(expr)) valueType := expr.Type() if expr.CommaOk { valueType = valueType.(*types.Tuple).At(0).Type() @@ -2139,13 +2139,13 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { case *ssa.MakeClosure: return b.parseMakeClosure(expr) case *ssa.MakeInterface: - val := b.getValue(expr.X) + val := b.getValue(expr.X, getPos(expr)) return b.createMakeInterface(val, expr.X.Type(), expr.Pos()), nil case *ssa.MakeMap: return b.createMakeMap(expr) case *ssa.MakeSlice: - sliceLen := b.getValue(expr.Len) - sliceCap := b.getValue(expr.Cap) + sliceLen := b.getValue(expr.Len, getPos(expr)) + sliceCap := b.getValue(expr.Cap, getPos(expr)) sliceType := expr.Type().Underlying().(*types.Slice) llvmElemType := b.getLLVMType(sliceType.Elem()) elemSize := b.targetData.TypeAllocSize(llvmElemType) @@ -2197,8 +2197,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { return slice, nil case *ssa.Next: rangeVal := expr.Iter.(*ssa.Range).X - llvmRangeVal := b.getValue(rangeVal) - it := b.getValue(expr.Iter) + llvmRangeVal := b.getValue(rangeVal, getPos(expr)) + it := b.getValue(expr.Iter, getPos(expr)) if expr.IsString { return b.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil } else { // map @@ -2224,14 +2224,14 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { case *ssa.Select: return b.createSelect(expr), nil case *ssa.Slice: - value := b.getValue(expr.X) + value := b.getValue(expr.X, getPos(expr)) var lowType, highType, maxType *types.Basic var low, high, max llvm.Value if expr.Low != nil { lowType = expr.Low.Type().Underlying().(*types.Basic) - low = b.getValue(expr.Low) + low = b.getValue(expr.Low, getPos(expr)) low = b.extendInteger(low, lowType, b.uintptrType) } else { lowType = types.Typ[types.Uintptr] @@ -2240,7 +2240,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { if expr.High != nil { highType = expr.High.Type().Underlying().(*types.Basic) - high = b.getValue(expr.High) + high = b.getValue(expr.High, getPos(expr)) high = b.extendInteger(high, highType, b.uintptrType) } else { highType = types.Typ[types.Uintptr] @@ -2248,7 +2248,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { if expr.Max != nil { maxType = expr.Max.Type().Underlying().(*types.Basic) - max = b.getValue(expr.Max) + max = b.getValue(expr.Max, getPos(expr)) max = b.extendInteger(max, maxType, b.uintptrType) } else { maxType = types.Typ[types.Uintptr] @@ -2381,7 +2381,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { // Conversion from a slice to an array pointer, as the name clearly // says. This requires a runtime check to make sure the slice is at // least as big as the array. - slice := b.getValue(expr.X) + slice := b.getValue(expr.X, getPos(expr)) sliceLen := b.CreateExtractValue(slice, 1, "") arrayLen := expr.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Array).Len() b.createSliceToArrayPointerCheck(sliceLen, arrayLen) @@ -2814,7 +2814,7 @@ func (b *builder) createBinOp(op token.Token, typ, ytyp types.Type, x, y llvm.Va } // createConst creates a LLVM constant value from a Go constant. -func (c *compilerContext) createConst(expr *ssa.Const) llvm.Value { +func (c *compilerContext) createConst(expr *ssa.Const, pos token.Pos) llvm.Value { switch typ := expr.Type().Underlying().(type) { case *types.Basic: llvmType := c.getLLVMType(typ) @@ -2860,15 +2860,15 @@ func (c *compilerContext) createConst(expr *ssa.Const) llvm.Value { n, _ := constant.Float64Val(expr.Value) return llvm.ConstFloat(llvmType, n) } else if typ.Kind() == types.Complex64 { - r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float32])) - i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float32])) + r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float32]), pos) + i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float32]), pos) cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false)) cplx = c.builder.CreateInsertValue(cplx, r, 0, "") cplx = c.builder.CreateInsertValue(cplx, i, 1, "") return cplx } else if typ.Kind() == types.Complex128 { - r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64])) - i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float64])) + r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64]), pos) + i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float64]), pos) cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)) cplx = c.builder.CreateInsertValue(cplx, r, 0, "") cplx = c.builder.CreateInsertValue(cplx, i, 1, "") @@ -3139,7 +3139,7 @@ func (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, p // which can all be directly lowered to IR. However, there is also the channel // receive operator which is handled in the runtime directly. func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) { - x := b.getValue(unop.X) + x := b.getValue(unop.X, getPos(unop)) switch unop.Op { case token.NOT: // !x return b.CreateNot(x, ""), nil diff --git a/compiler/defer.go b/compiler/defer.go index 99b31435..a7739c9d 100644 --- a/compiler/defer.go +++ b/compiler/defer.go @@ -267,13 +267,13 @@ func (b *builder) createDefer(instr *ssa.Defer) { // Collect all values to be put in the struct (starting with // runtime._defer fields, followed by the call parameters). - itf := b.getValue(instr.Call.Value) // interface + itf := b.getValue(instr.Call.Value, getPos(instr)) // interface typecode := b.CreateExtractValue(itf, 0, "invoke.func.typecode") receiverValue := b.CreateExtractValue(itf, 1, "invoke.func.receiver") values = []llvm.Value{callback, next, typecode, receiverValue} valueTypes = append(valueTypes, b.i8ptrType, b.i8ptrType) for _, arg := range instr.Call.Args { - val := b.getValue(arg) + val := b.getValue(arg, getPos(instr)) values = append(values, val) valueTypes = append(valueTypes, val.Type()) } @@ -290,7 +290,7 @@ func (b *builder) createDefer(instr *ssa.Defer) { // runtime._defer fields). values = []llvm.Value{callback, next} for _, param := range instr.Call.Args { - llvmParam := b.getValue(param) + llvmParam := b.getValue(param, getPos(instr)) values = append(values, llvmParam) valueTypes = append(valueTypes, llvmParam.Type()) } @@ -302,7 +302,7 @@ func (b *builder) createDefer(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 := b.getValue(instr.Call.Value) + closure := b.getValue(instr.Call.Value, getPos(instr)) context := b.CreateExtractValue(closure, 0, "") // Get the callback number. @@ -318,7 +318,7 @@ func (b *builder) createDefer(instr *ssa.Defer) { // context pointer). values = []llvm.Value{callback, next} for _, param := range instr.Call.Args { - llvmParam := b.getValue(param) + llvmParam := b.getValue(param, getPos(instr)) values = append(values, llvmParam) valueTypes = append(valueTypes, llvmParam.Type()) } @@ -330,7 +330,7 @@ func (b *builder) createDefer(instr *ssa.Defer) { var argValues []llvm.Value for _, arg := range instr.Call.Args { argTypes = append(argTypes, arg.Type()) - argValues = append(argValues, b.getValue(arg)) + argValues = append(argValues, b.getValue(arg, getPos(instr))) } if _, ok := b.deferBuiltinFuncs[instr.Call.Value]; !ok { @@ -353,7 +353,7 @@ func (b *builder) createDefer(instr *ssa.Defer) { } } else { - funcValue := b.getValue(instr.Call.Value) + funcValue := b.getValue(instr.Call.Value, getPos(instr)) if _, ok := b.deferExprFuncs[instr.Call.Value]; !ok { b.deferExprFuncs[instr.Call.Value] = len(b.allDeferFuncs) @@ -368,7 +368,7 @@ func (b *builder) createDefer(instr *ssa.Defer) { values = []llvm.Value{callback, next, funcValue} valueTypes = append(valueTypes, funcValue.Type()) for _, param := range instr.Call.Args { - llvmParam := b.getValue(param) + llvmParam := b.getValue(param, getPos(instr)) values = append(values, llvmParam) valueTypes = append(valueTypes, llvmParam.Type()) } diff --git a/compiler/func.go b/compiler/func.go index 404c7316..743a4f08 100644 --- a/compiler/func.go +++ b/compiler/func.go @@ -134,7 +134,7 @@ func (b *builder) parseMakeClosure(expr *ssa.MakeClosure) (llvm.Value, error) { boundVars := make([]llvm.Value, len(expr.Bindings)) for i, binding := range expr.Bindings { // The context stores the bound variables. - llvmBoundVar := b.getValue(binding) + llvmBoundVar := b.getValue(binding, getPos(expr)) boundVars[i] = llvmBoundVar } diff --git a/compiler/goroutine.go b/compiler/goroutine.go index da4e32ae..8feb5e79 100644 --- a/compiler/goroutine.go +++ b/compiler/goroutine.go @@ -16,7 +16,7 @@ func (b *builder) createGo(instr *ssa.Go) { // Get all function parameters to pass to the goroutine. var params []llvm.Value for _, param := range instr.Call.Args { - params = append(params, b.getValue(param)) + params = append(params, b.getValue(param, getPos(instr))) } var prefix string @@ -33,7 +33,7 @@ func (b *builder) createGo(instr *ssa.Go) { case *ssa.MakeClosure: // A goroutine call on a func value, but the callee is trivial to find. For // example: immediately applied functions. - funcValue := b.getValue(value) + funcValue := b.getValue(value, getPos(instr)) context = b.extractFuncContext(funcValue) default: panic("StaticCallee returned an unexpected value") @@ -70,13 +70,13 @@ func (b *builder) createGo(instr *ssa.Go) { var argValues []llvm.Value for _, arg := range instr.Call.Args { argTypes = append(argTypes, arg.Type()) - argValues = append(argValues, b.getValue(arg)) + argValues = append(argValues, b.getValue(arg, getPos(instr))) } b.createBuiltin(argTypes, argValues, builtin.Name(), instr.Pos()) return } else if instr.Call.IsInvoke() { // This is a method call on an interface value. - itf := b.getValue(instr.Call.Value) + itf := b.getValue(instr.Call.Value, getPos(instr)) itfTypeCode := b.CreateExtractValue(itf, 0, "") itfValue := b.CreateExtractValue(itf, 1, "") funcPtr = b.getInvokeFunction(&instr.Call) @@ -90,7 +90,7 @@ func (b *builder) createGo(instr *ssa.Go) { // * The function context, for closures. // * The function pointer (for tasks). var context llvm.Value - funcPtrType, funcPtr, context = b.decodeFuncValue(b.getValue(instr.Call.Value), instr.Call.Value.Type().Underlying().(*types.Signature)) + funcPtrType, funcPtr, context = b.decodeFuncValue(b.getValue(instr.Call.Value, getPos(instr)), instr.Call.Value.Type().Underlying().(*types.Signature)) params = append(params, context, funcPtr) hasContext = true prefix = b.fn.RelString(nil) diff --git a/compiler/inlineasm.go b/compiler/inlineasm.go index 2afb0a16..72dd68cf 100644 --- a/compiler/inlineasm.go +++ b/compiler/inlineasm.go @@ -5,6 +5,7 @@ package compiler import ( "fmt" "go/constant" + "go/token" "regexp" "strconv" "strings" @@ -55,7 +56,7 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) 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) - registers[key] = b.getValue(r.Value.(*ssa.MakeInterface).X) + registers[key] = b.getValue(r.Value.(*ssa.MakeInterface).X, getPos(instr)) case *ssa.Call: if r.Common() == instr { break @@ -140,7 +141,7 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) // // The num parameter must be a constant. All other parameters may be any scalar // value supported by LLVM inline assembly. -func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) { +func (b *builder) emitSVCall(args []ssa.Value, pos token.Pos) (llvm.Value, error) { num, _ := constant.Uint64Val(args[0].(*ssa.Const).Value) llvmArgs := []llvm.Value{} argTypes := []llvm.Type{} @@ -153,7 +154,7 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) { } else { constraints += ",{r" + strconv.Itoa(i) + "}" } - llvmValue := b.getValue(arg) + llvmValue := b.getValue(arg, pos) llvmArgs = append(llvmArgs, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -178,7 +179,7 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) { // The num parameter must be a constant. All other parameters may be any scalar // value supported by LLVM inline assembly. // Same as emitSVCall but for AArch64 -func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error) { +func (b *builder) emitSV64Call(args []ssa.Value, pos token.Pos) (llvm.Value, error) { num, _ := constant.Uint64Val(args[0].(*ssa.Const).Value) llvmArgs := []llvm.Value{} argTypes := []llvm.Type{} @@ -191,7 +192,7 @@ func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error) { } else { constraints += ",{x" + strconv.Itoa(i) + "}" } - llvmValue := b.getValue(arg) + llvmValue := b.getValue(arg, pos) llvmArgs = append(llvmArgs, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -231,19 +232,19 @@ func (b *builder) emitCSROperation(call *ssa.CallCommon) (llvm.Value, error) { 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, false) - return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil + return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1], getPos(call))}, ""), nil case "SetBits": // Note: it may be possible to optimize this to csrrsi in many cases. 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, false) - return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil + return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1], getPos(call))}, ""), nil case "ClearBits": // Note: it may be possible to optimize this to csrrci in many cases. 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, false) - return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil + return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1], getPos(call))}, ""), nil default: return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation: "+name) } diff --git a/compiler/interface.go b/compiler/interface.go index 097eadcf..51101065 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -475,7 +475,7 @@ func (c *compilerContext) 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 (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value { - itf := b.getValue(expr.X) + itf := b.getValue(expr.X, getPos(expr)) assertedType := b.getLLVMType(expr.AssertedType) actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type") diff --git a/compiler/interrupt.go b/compiler/interrupt.go index c1f7d69f..1fb4c22b 100644 --- a/compiler/interrupt.go +++ b/compiler/interrupt.go @@ -24,7 +24,7 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro // 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 := b.getValue(instr.Args[1]) + funcValue := b.getValue(instr.Args[1], getPos(instr)) if funcValue.IsAConstant().IsNil() { // Try to determine the cause of the non-constantness for a nice error // message. diff --git a/compiler/intrinsics.go b/compiler/intrinsics.go index e59fdc44..c196b60d 100644 --- a/compiler/intrinsics.go +++ b/compiler/intrinsics.go @@ -58,7 +58,7 @@ func (b *builder) createMemoryCopyImpl() { } var params []llvm.Value for _, param := range b.fn.Params { - params = append(params, b.getValue(param)) + params = append(params, b.getValue(param, getPos(b.fn))) } params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false)) b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "") @@ -80,9 +80,9 @@ func (b *builder) createMemoryZeroImpl() { llvmFn = llvm.AddFunction(b.mod, fnName, fnType) } params := []llvm.Value{ - b.getValue(b.fn.Params[0]), + b.getValue(b.fn.Params[0], getPos(b.fn)), llvm.ConstInt(b.ctx.Int8Type(), 0, false), - b.getValue(b.fn.Params[1]), + b.getValue(b.fn.Params[1], getPos(b.fn)), llvm.ConstInt(b.ctx.Int1Type(), 0, false), } b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "") @@ -95,7 +95,7 @@ func (b *builder) createKeepAliveImpl() { b.createFunctionStart(true) // Get the underlying value of the interface value. - interfaceValue := b.getValue(b.fn.Params[0]) + interfaceValue := b.getValue(b.fn.Params[0], getPos(b.fn)) pointerValue := b.CreateExtractValue(interfaceValue, 1, "") // Create an equivalent of the following C code, which is basically just a @@ -149,7 +149,7 @@ func (b *builder) defineMathOp() { // Create a call to the intrinsic. args := make([]llvm.Value, len(b.fn.Params)) for i, param := range b.fn.Params { - args[i] = b.getValue(param) + args[i] = b.getValue(param, getPos(b.fn)) } result := b.CreateCall(llvmFn.GlobalValueType(), llvmFn, args, "") b.CreateRet(result) diff --git a/compiler/map.go b/compiler/map.go index 632ff247..9c9a3b5c 100644 --- a/compiler/map.go +++ b/compiler/map.go @@ -46,7 +46,7 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) { sizeHint := llvm.ConstInt(b.uintptrType, 8, false) algEnum := llvm.ConstInt(b.ctx.Int8Type(), alg, false) if expr.Reserve != nil { - sizeHint = b.getValue(expr.Reserve) + sizeHint = b.getValue(expr.Reserve, getPos(expr)) var err error sizeHint, err = b.createConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos()) if err != nil { diff --git a/compiler/syscall.go b/compiler/syscall.go index 66baf826..db1ffd70 100644 --- a/compiler/syscall.go +++ b/compiler/syscall.go @@ -14,7 +14,7 @@ import ( // and returns the result as a single integer (the system call result). The // result is not further interpreted. func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { - num := b.getValue(call.Args[0]) + num := b.getValue(call.Args[0], getPos(call)) switch { case b.GOARCH == "amd64" && b.GOOS == "linux": // Sources: @@ -37,7 +37,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { "{r12}", "{r13}", }[i] - llvmValue := b.getValue(arg) + llvmValue := b.getValue(arg, getPos(call)) args = append(args, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -64,7 +64,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { "{edi}", "{ebp}", }[i] - llvmValue := b.getValue(arg) + llvmValue := b.getValue(arg, getPos(call)) args = append(args, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -89,7 +89,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { "{r5}", "{r6}", }[i] - llvmValue := b.getValue(arg) + llvmValue := b.getValue(arg, getPos(call)) args = append(args, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -119,7 +119,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { "{x4}", "{x5}", }[i] - llvmValue := b.getValue(arg) + llvmValue := b.getValue(arg, getPos(call)) args = append(args, llvmValue) argTypes = append(argTypes, llvmValue.Type()) } @@ -177,12 +177,12 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) { var paramTypes []llvm.Type var params []llvm.Value for _, val := range call.Args[2:] { - param := b.getValue(val) + param := b.getValue(val, getPos(call)) params = append(params, param) paramTypes = append(paramTypes, param.Type()) } llvmType := llvm.FunctionType(b.uintptrType, paramTypes, false) - fn := b.getValue(call.Args[0]) + fn := b.getValue(call.Args[0], getPos(call)) fnPtr := b.CreateIntToPtr(fn, llvm.PointerType(llvmType, 0), "") // Prepare some functions that will be called later. diff --git a/compiler/volatile.go b/compiler/volatile.go index 3d3a67fa..0f7e7b22 100644 --- a/compiler/volatile.go +++ b/compiler/volatile.go @@ -9,7 +9,7 @@ import "go/types" // runtime/volatile.LoadT(). func (b *builder) createVolatileLoad() { b.createFunctionStart(true) - addr := b.getValue(b.fn.Params[0]) + addr := b.getValue(b.fn.Params[0], getPos(b.fn)) b.createNilCheck(b.fn.Params[0], addr, "deref") valType := b.getLLVMType(b.fn.Params[0].Type().(*types.Pointer).Elem()) val := b.CreateLoad(valType, addr, "") @@ -21,8 +21,8 @@ func (b *builder) createVolatileLoad() { // runtime/volatile.StoreT(). func (b *builder) createVolatileStore() { b.createFunctionStart(true) - addr := b.getValue(b.fn.Params[0]) - val := b.getValue(b.fn.Params[1]) + addr := b.getValue(b.fn.Params[0], getPos(b.fn)) + val := b.getValue(b.fn.Params[1], getPos(b.fn)) b.createNilCheck(b.fn.Params[0], addr, "deref") store := b.CreateStore(val, addr) store.SetVolatile(true)