Browse Source

compiler; add position information to createConstant

Non-functional change. The position information will be used later to
emit debug info locations to string constants.
pull/3522/head
Ayke van Laethem 2 years ago
committed by Ayke
parent
commit
0ce539ad42
  1. 20
      compiler/atomic.go
  2. 16
      compiler/channel.go
  3. 100
      compiler/compiler.go
  4. 16
      compiler/defer.go
  5. 2
      compiler/func.go
  6. 10
      compiler/goroutine.go
  7. 17
      compiler/inlineasm.go
  8. 2
      compiler/interface.go
  9. 2
      compiler/interrupt.go
  10. 10
      compiler/intrinsics.go
  11. 2
      compiler/map.go
  12. 14
      compiler/syscall.go
  13. 6
      compiler/volatile.go

20
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()

16
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

100
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

16
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())
}

2
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
}

10
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)

17
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)
}

2
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")

2
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.

10
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)

2
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 {

14
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.

6
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)

Loading…
Cancel
Save