compiler; add position information to createConstant

Non-functional change. The position information will be used later to
emit debug info locations to string constants.
Этот коммит содержится в:
Ayke van Laethem 2023-03-05 17:34:36 +01:00 коммит произвёл Ayke
родитель 930255ff46
коммит 0ce539ad42
13 изменённых файлов: 109 добавлений и 108 удалений

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

@ -13,8 +13,8 @@ import (
func (b *builder) createAtomicOp(name string) llvm.Value { func (b *builder) createAtomicOp(name string) llvm.Value {
switch name { switch name {
case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr": case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
ptr := b.getValue(b.fn.Params[0]) ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1]) val := b.getValue(b.fn.Params[1], getPos(b.fn))
if strings.HasPrefix(b.Triple, "avr") { if strings.HasPrefix(b.Triple, "avr") {
// AtomicRMW does not work on AVR as intended: // 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) // - 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 the new value, not the original value returned by atomicrmw.
return b.CreateAdd(oldVal, val, "") return b.CreateAdd(oldVal, val, "")
case "SwapInt32", "SwapInt64", "SwapUint32", "SwapUint64", "SwapUintptr", "SwapPointer": case "SwapInt32", "SwapInt64", "SwapUint32", "SwapUint64", "SwapUintptr", "SwapPointer":
ptr := b.getValue(b.fn.Params[0]) ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1]) val := b.getValue(b.fn.Params[1], getPos(b.fn))
isPointer := val.Type().TypeKind() == llvm.PointerTypeKind isPointer := val.Type().TypeKind() == llvm.PointerTypeKind
if isPointer { if isPointer {
// atomicrmw only supports integers, so cast to an integer. // atomicrmw only supports integers, so cast to an integer.
@ -48,21 +48,21 @@ func (b *builder) createAtomicOp(name string) llvm.Value {
} }
return oldVal return oldVal
case "CompareAndSwapInt32", "CompareAndSwapInt64", "CompareAndSwapUint32", "CompareAndSwapUint64", "CompareAndSwapUintptr", "CompareAndSwapPointer": case "CompareAndSwapInt32", "CompareAndSwapInt64", "CompareAndSwapUint32", "CompareAndSwapUint64", "CompareAndSwapUintptr", "CompareAndSwapPointer":
ptr := b.getValue(b.fn.Params[0]) ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
old := b.getValue(b.fn.Params[1]) old := b.getValue(b.fn.Params[1], getPos(b.fn))
newVal := b.getValue(b.fn.Params[2]) newVal := b.getValue(b.fn.Params[2], getPos(b.fn))
tuple := b.CreateAtomicCmpXchg(ptr, old, newVal, llvm.AtomicOrderingSequentiallyConsistent, llvm.AtomicOrderingSequentiallyConsistent, true) tuple := b.CreateAtomicCmpXchg(ptr, old, newVal, llvm.AtomicOrderingSequentiallyConsistent, llvm.AtomicOrderingSequentiallyConsistent, true)
swapped := b.CreateExtractValue(tuple, 1, "") swapped := b.CreateExtractValue(tuple, 1, "")
return swapped return swapped
case "LoadInt32", "LoadInt64", "LoadUint32", "LoadUint64", "LoadUintptr", "LoadPointer": 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 := b.CreateLoad(b.getLLVMType(b.fn.Signature.Results().At(0).Type()), ptr, "")
val.SetOrdering(llvm.AtomicOrderingSequentiallyConsistent) val.SetOrdering(llvm.AtomicOrderingSequentiallyConsistent)
val.SetAlignment(b.targetData.PrefTypeAlignment(val.Type())) // required val.SetAlignment(b.targetData.PrefTypeAlignment(val.Type())) // required
return val return val
case "StoreInt32", "StoreInt64", "StoreUint32", "StoreUint64", "StoreUintptr", "StorePointer": case "StoreInt32", "StoreInt64", "StoreUint32", "StoreUint64", "StoreUintptr", "StorePointer":
ptr := b.getValue(b.fn.Params[0]) ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1]) val := b.getValue(b.fn.Params[1], getPos(b.fn))
if strings.HasPrefix(b.Triple, "avr") { if strings.HasPrefix(b.Triple, "avr") {
// SelectionDAGBuilder is currently missing the "are unaligned atomics allowed" check for stores. // SelectionDAGBuilder is currently missing the "are unaligned atomics allowed" check for stores.
vType := val.Type() vType := val.Type()

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

@ -14,7 +14,7 @@ import (
func (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value { func (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value {
elementSize := b.targetData.TypeAllocSize(b.getLLVMType(expr.Type().Underlying().(*types.Chan).Elem())) elementSize := b.targetData.TypeAllocSize(b.getLLVMType(expr.Type().Underlying().(*types.Chan).Elem()))
elementSizeValue := llvm.ConstInt(b.uintptrType, elementSize, false) 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()) b.createChanBoundsCheck(elementSize, bufSize, expr.Size.Type().Underlying().(*types.Basic), expr.Pos())
if bufSize.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() { if bufSize.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {
bufSize = b.CreateZExt(bufSize, b.uintptrType, "") 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 // createChanSend emits a pseudo chan send operation. It is lowered to the
// actual channel send operation during goroutine lowering. // actual channel send operation during goroutine lowering.
func (b *builder) createChanSend(instr *ssa.Send) { func (b *builder) createChanSend(instr *ssa.Send) {
ch := b.getValue(instr.Chan) ch := b.getValue(instr.Chan, getPos(instr))
chanValue := b.getValue(instr.X) chanValue := b.getValue(instr.X, getPos(instr))
// store value-to-send // store value-to-send
valueType := b.getLLVMType(instr.X.Type()) valueType := b.getLLVMType(instr.X.Type())
@ -62,7 +62,7 @@ func (b *builder) createChanSend(instr *ssa.Send) {
// actual channel receive operation during goroutine lowering. // actual channel receive operation during goroutine lowering.
func (b *builder) createChanRecv(unop *ssa.UnOp) llvm.Value { func (b *builder) createChanRecv(unop *ssa.UnOp) llvm.Value {
valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Chan).Elem()) 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. // Allocate memory to receive into.
isZeroSize := b.targetData.TypeAllocSize(valueType) == 0 isZeroSize := b.targetData.TypeAllocSize(valueType) == 0
@ -140,7 +140,7 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
var selectStates []llvm.Value var selectStates []llvm.Value
chanSelectStateType := b.getLLVMRuntimeType("chanSelectState") chanSelectStateType := b.getLLVMRuntimeType("chanSelectState")
for _, state := range expr.States { for _, state := range expr.States {
ch := b.getValue(state.Chan) ch := b.getValue(state.Chan, state.Pos)
selectState := llvm.ConstNull(chanSelectStateType) selectState := llvm.ConstNull(chanSelectStateType)
selectState = b.CreateInsertValue(selectState, ch, 0, "") selectState = b.CreateInsertValue(selectState, ch, 0, "")
switch state.Dir { switch state.Dir {
@ -156,7 +156,7 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
case types.SendOnly: case types.SendOnly:
// Store this value in an alloca and put a pointer to this alloca // Store this value in an alloca and put a pointer to this alloca
// in the send state. // in the send state.
sendValue := b.getValue(state.Send) sendValue := b.getValue(state.Send, state.Pos)
alloca := llvmutil.CreateEntryBlockAlloca(b.Builder, sendValue.Type(), "select.send.value") alloca := llvmutil.CreateEntryBlockAlloca(b.Builder, sendValue.Type(), "select.send.value")
b.CreateStore(sendValue, alloca) b.CreateStore(sendValue, alloca)
ptr := b.CreateBitCast(alloca, b.i8ptrType, "") 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 { func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value {
if expr.Index == 0 { if expr.Index == 0 {
// index // index
value := b.getValue(expr.Tuple) value := b.getValue(expr.Tuple, getPos(expr))
index := b.CreateExtractValue(value, expr.Index, "") index := b.CreateExtractValue(value, expr.Index, "")
if index.Type().IntTypeWidth() < b.intType.IntTypeWidth() { if index.Type().IntTypeWidth() < b.intType.IntTypeWidth() {
index = b.CreateSExt(index, b.intType, "") index = b.CreateSExt(index, b.intType, "")
@ -255,7 +255,7 @@ func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value {
return index return index
} else if expr.Index == 1 { } else if expr.Index == 1 {
// comma-ok // comma-ok
value := b.getValue(expr.Tuple) value := b.getValue(expr.Tuple, getPos(expr))
return b.CreateExtractValue(value, expr.Index, "") return b.CreateExtractValue(value, expr.Index, "")
} else { } else {
// Select statements are (index, ok, ...) where ... is a number of // Select statements are (index, ok, ...) where ... is a number of

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

@ -1028,7 +1028,7 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global, global llvm.Valu
var fileStructs []llvm.Value var fileStructs []llvm.Value
for _, file := range allFiles { for _, file := range allFiles {
fileStruct := llvm.ConstNull(llvmEmbedFileStructType) 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 fileStruct = c.builder.CreateInsertValue(fileStruct, name, 0, "") // "name" field
if file.Hash != "" { if file.Hash != "" {
data := c.getEmbedFileString(file) data := c.getEmbedFileString(file)
@ -1321,7 +1321,7 @@ func (b *builder) createFunction() {
} }
dbgVar := b.getLocalVariable(variable) dbgVar := b.getLocalVariable(variable)
pos := b.program.Fset.Position(instr.Pos()) 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), Line: uint(pos.Line),
Col: uint(pos.Column), Col: uint(pos.Column),
Scope: b.difunc, Scope: b.difunc,
@ -1352,7 +1352,7 @@ func (b *builder) createFunction() {
for _, phi := range b.phis { for _, phi := range b.phis {
block := phi.ssa.Block() block := phi.ssa.Block()
for i, edge := range phi.ssa.Edges { for i, edge := range phi.ssa.Edges {
llvmVal := b.getValue(edge) llvmVal := b.getValue(edge, getPos(phi.ssa))
llvmBlock := b.blockExits[block.Preds[i]] llvmBlock := b.blockExits[block.Preds[i]]
phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock}) phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock})
} }
@ -1460,7 +1460,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
// Start a new goroutine. // Start a new goroutine.
b.createGo(instr) b.createGo(instr)
case *ssa.If: case *ssa.If:
cond := b.getValue(instr.Cond) cond := b.getValue(instr.Cond, getPos(instr))
block := instr.Block() block := instr.Block()
blockThen := b.blockEntries[block.Succs[0]] blockThen := b.blockEntries[block.Succs[0]]
blockElse := b.blockEntries[block.Succs[1]] blockElse := b.blockEntries[block.Succs[1]]
@ -1469,13 +1469,13 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
blockJump := b.blockEntries[instr.Block().Succs[0]] blockJump := b.blockEntries[instr.Block().Succs[0]]
b.CreateBr(blockJump) b.CreateBr(blockJump)
case *ssa.MapUpdate: case *ssa.MapUpdate:
m := b.getValue(instr.Map) m := b.getValue(instr.Map, getPos(instr))
key := b.getValue(instr.Key) key := b.getValue(instr.Key, getPos(instr))
value := b.getValue(instr.Value) value := b.getValue(instr.Value, getPos(instr))
mapType := instr.Map.Type().Underlying().(*types.Map) mapType := instr.Map.Type().Underlying().(*types.Map)
b.createMapUpdate(mapType.Key(), m, key, value, instr.Pos()) b.createMapUpdate(mapType.Key(), m, key, value, instr.Pos())
case *ssa.Panic: case *ssa.Panic:
value := b.getValue(instr.X) value := b.getValue(instr.X, getPos(instr))
b.createRuntimeInvoke("_panic", []llvm.Value{value}, "") b.createRuntimeInvoke("_panic", []llvm.Value{value}, "")
b.CreateUnreachable() b.CreateUnreachable()
case *ssa.Return: case *ssa.Return:
@ -1485,12 +1485,12 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
if len(instr.Results) == 0 { if len(instr.Results) == 0 {
b.CreateRetVoid() b.CreateRetVoid()
} else if len(instr.Results) == 1 { } else if len(instr.Results) == 1 {
b.CreateRet(b.getValue(instr.Results[0])) b.CreateRet(b.getValue(instr.Results[0], getPos(instr)))
} else { } else {
// Multiple return values. Put them all in a struct. // Multiple return values. Put them all in a struct.
retVal := llvm.ConstNull(b.llvmFn.GlobalValueType().ReturnType()) retVal := llvm.ConstNull(b.llvmFn.GlobalValueType().ReturnType())
for i, result := range instr.Results { for i, result := range instr.Results {
val := b.getValue(result) val := b.getValue(result, getPos(instr))
retVal = b.CreateInsertValue(retVal, val, i, "") retVal = b.CreateInsertValue(retVal, val, i, "")
} }
b.CreateRet(retVal) b.CreateRet(retVal)
@ -1500,8 +1500,8 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
case *ssa.Send: case *ssa.Send:
b.createChanSend(instr) b.createChanSend(instr)
case *ssa.Store: case *ssa.Store:
llvmAddr := b.getValue(instr.Addr) llvmAddr := b.getValue(instr.Addr, getPos(instr))
llvmVal := b.getValue(instr.Val) llvmVal := b.getValue(instr.Val, getPos(instr))
b.createNilCheck(instr.Addr, llvmAddr, "store") b.createNilCheck(instr.Addr, llvmAddr, "store")
if b.targetData.TypeAllocSize(llvmVal.Type()) == 0 { if b.targetData.TypeAllocSize(llvmVal.Type()) == 0 {
// nothing to store // 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) { func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) {
var params []llvm.Value var params []llvm.Value
for _, param := range instr.Args { 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. // 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": case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
return b.createInlineAsmFull(instr) return b.createInlineAsmFull(instr)
case strings.HasPrefix(name, "device/arm.SVCall"): 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"): 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)."): case strings.HasPrefix(name, "(device/riscv.CSR)."):
return b.emitCSROperation(instr) return b.emitCSROperation(instr)
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall"): 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: case *ssa.MakeClosure:
// A call on a func value, but the callee is trivial to find. For // A call on a func value, but the callee is trivial to find. For
// example: immediately applied functions. // example: immediately applied functions.
funcValue := b.getValue(value) funcValue := b.getValue(value, getPos(value))
context = b.extractFuncContext(funcValue) context = b.extractFuncContext(funcValue)
default: default:
panic("StaticCallee returned an unexpected value") 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()) return b.createBuiltin(argTypes, params, call.Name(), instr.Pos())
} else if instr.IsInvoke() { } else if instr.IsInvoke() {
// Interface method call (aka invoke call). // 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") typecode := b.CreateExtractValue(itf, 0, "invoke.func.typecode")
value := b.CreateExtractValue(itf, 1, "invoke.func.value") // receiver value := b.CreateExtractValue(itf, 1, "invoke.func.value") // receiver
// Prefix the params with receiver value and suffix with typecode. // 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) context = llvm.Undef(b.i8ptrType)
} else { } else {
// Function pointer. // 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 // This is a func value, which cannot be called directly. We have to
// extract the function pointer and context first from the func value. // extract the function pointer and context first from the func value.
calleeType, callee, context = b.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature)) 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 // getValue returns the LLVM value of a constant, function value, global, or
// already processed SSA expression. // 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) { switch expr := expr.(type) {
case *ssa.Const: case *ssa.Const:
return b.createConst(expr) return b.createConst(expr, pos)
case *ssa.Function: case *ssa.Function:
if b.getFunctionInfo(expr).exported { if b.getFunctionInfo(expr).exported {
b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String()) b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String())
@ -1948,8 +1948,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
return buf, nil return buf, nil
} }
case *ssa.BinOp: case *ssa.BinOp:
x := b.getValue(expr.X) x := b.getValue(expr.X, getPos(expr))
y := b.getValue(expr.Y) y := b.getValue(expr.Y, getPos(expr))
return b.createBinOp(expr.Op, expr.X.Type(), expr.Y.Type(), x, y, expr.Pos()) return b.createBinOp(expr.Op, expr.X.Type(), expr.Y.Type(), x, y, expr.Pos())
case *ssa.Call: case *ssa.Call:
return b.createFunctionCall(expr.Common()) 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 // This is different from how the official Go compiler works, because of
// heap allocation and because it's easier to implement, see: // heap allocation and because it's easier to implement, see:
// https://research.swtch.com/interfaces // https://research.swtch.com/interfaces
return b.getValue(expr.X), nil return b.getValue(expr.X, getPos(expr)), nil
case *ssa.ChangeType: case *ssa.ChangeType:
// This instruction changes the type, but the underlying value remains // This instruction changes the type, but the underlying value remains
// the same. This is often a no-op, but sometimes we have to change the // the same. This is often a no-op, but sometimes we have to change the
// LLVM type as well. // LLVM type as well.
x := b.getValue(expr.X) x := b.getValue(expr.X, getPos(expr))
llvmType := b.getLLVMType(expr.Type()) llvmType := b.getLLVMType(expr.Type())
if x.Type() == llvmType { if x.Type() == llvmType {
// Different Go type but same LLVM type (for example, named int). // Different Go type but same LLVM type (for example, named int).
@ -1994,20 +1994,20 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
case *ssa.Const: case *ssa.Const:
panic("const is not an expression") panic("const is not an expression")
case *ssa.Convert: case *ssa.Convert:
x := b.getValue(expr.X) x := b.getValue(expr.X, getPos(expr))
return b.createConvert(expr.X.Type(), expr.Type(), x, expr.Pos()) return b.createConvert(expr.X.Type(), expr.Type(), x, expr.Pos())
case *ssa.Extract: case *ssa.Extract:
if _, ok := expr.Tuple.(*ssa.Select); ok { if _, ok := expr.Tuple.(*ssa.Select); ok {
return b.getChanSelectResult(expr), nil return b.getChanSelectResult(expr), nil
} }
value := b.getValue(expr.Tuple) value := b.getValue(expr.Tuple, getPos(expr))
return b.CreateExtractValue(value, expr.Index, ""), nil return b.CreateExtractValue(value, expr.Index, ""), nil
case *ssa.Field: case *ssa.Field:
value := b.getValue(expr.X) value := b.getValue(expr.X, getPos(expr))
result := b.CreateExtractValue(value, expr.Field, "") result := b.CreateExtractValue(value, expr.Field, "")
return result, nil return result, nil
case *ssa.FieldAddr: 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: // Check for nil pointer before calculating the address, from the spec:
// > For an operand x of type T, the address operation &x generates a // > For an operand x of type T, the address operation &x generates a
// > pointer of type *T to x. [...] If the evaluation of x would cause a // > pointer of type *T to x. [...] If the evaluation of x would cause a
@ -2025,8 +2025,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
case *ssa.Global: case *ssa.Global:
panic("global is not an expression") panic("global is not an expression")
case *ssa.Index: case *ssa.Index:
collection := b.getValue(expr.X) collection := b.getValue(expr.X, getPos(expr))
index := b.getValue(expr.Index) index := b.getValue(expr.Index, getPos(expr))
switch xType := expr.X.Type().Underlying().(type) { switch xType := expr.X.Type().Underlying().(type) {
case *types.Basic: // extract byte from string 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") panic("unknown *ssa.Index type")
} }
case *ssa.IndexAddr: case *ssa.IndexAddr:
val := b.getValue(expr.X) val := b.getValue(expr.X, getPos(expr))
index := b.getValue(expr.Index) index := b.getValue(expr.Index, getPos(expr))
// Get buffer pointer and length // Get buffer pointer and length
var bufptr, buflen llvm.Value var bufptr, buflen llvm.Value
@ -2127,8 +2127,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
panic("unreachable") panic("unreachable")
} }
case *ssa.Lookup: // map lookup case *ssa.Lookup: // map lookup
value := b.getValue(expr.X) value := b.getValue(expr.X, getPos(expr))
index := b.getValue(expr.Index) index := b.getValue(expr.Index, getPos(expr))
valueType := expr.Type() valueType := expr.Type()
if expr.CommaOk { if expr.CommaOk {
valueType = valueType.(*types.Tuple).At(0).Type() valueType = valueType.(*types.Tuple).At(0).Type()
@ -2139,13 +2139,13 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
case *ssa.MakeClosure: case *ssa.MakeClosure:
return b.parseMakeClosure(expr) return b.parseMakeClosure(expr)
case *ssa.MakeInterface: 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 return b.createMakeInterface(val, expr.X.Type(), expr.Pos()), nil
case *ssa.MakeMap: case *ssa.MakeMap:
return b.createMakeMap(expr) return b.createMakeMap(expr)
case *ssa.MakeSlice: case *ssa.MakeSlice:
sliceLen := b.getValue(expr.Len) sliceLen := b.getValue(expr.Len, getPos(expr))
sliceCap := b.getValue(expr.Cap) sliceCap := b.getValue(expr.Cap, getPos(expr))
sliceType := expr.Type().Underlying().(*types.Slice) sliceType := expr.Type().Underlying().(*types.Slice)
llvmElemType := b.getLLVMType(sliceType.Elem()) llvmElemType := b.getLLVMType(sliceType.Elem())
elemSize := b.targetData.TypeAllocSize(llvmElemType) elemSize := b.targetData.TypeAllocSize(llvmElemType)
@ -2197,8 +2197,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
return slice, nil return slice, nil
case *ssa.Next: case *ssa.Next:
rangeVal := expr.Iter.(*ssa.Range).X rangeVal := expr.Iter.(*ssa.Range).X
llvmRangeVal := b.getValue(rangeVal) llvmRangeVal := b.getValue(rangeVal, getPos(expr))
it := b.getValue(expr.Iter) it := b.getValue(expr.Iter, getPos(expr))
if expr.IsString { if expr.IsString {
return b.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil return b.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
} else { // map } else { // map
@ -2224,14 +2224,14 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
case *ssa.Select: case *ssa.Select:
return b.createSelect(expr), nil return b.createSelect(expr), nil
case *ssa.Slice: case *ssa.Slice:
value := b.getValue(expr.X) value := b.getValue(expr.X, getPos(expr))
var lowType, highType, maxType *types.Basic var lowType, highType, maxType *types.Basic
var low, high, max llvm.Value var low, high, max llvm.Value
if expr.Low != nil { if expr.Low != nil {
lowType = expr.Low.Type().Underlying().(*types.Basic) lowType = expr.Low.Type().Underlying().(*types.Basic)
low = b.getValue(expr.Low) low = b.getValue(expr.Low, getPos(expr))
low = b.extendInteger(low, lowType, b.uintptrType) low = b.extendInteger(low, lowType, b.uintptrType)
} else { } else {
lowType = types.Typ[types.Uintptr] lowType = types.Typ[types.Uintptr]
@ -2240,7 +2240,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
if expr.High != nil { if expr.High != nil {
highType = expr.High.Type().Underlying().(*types.Basic) highType = expr.High.Type().Underlying().(*types.Basic)
high = b.getValue(expr.High) high = b.getValue(expr.High, getPos(expr))
high = b.extendInteger(high, highType, b.uintptrType) high = b.extendInteger(high, highType, b.uintptrType)
} else { } else {
highType = types.Typ[types.Uintptr] highType = types.Typ[types.Uintptr]
@ -2248,7 +2248,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
if expr.Max != nil { if expr.Max != nil {
maxType = expr.Max.Type().Underlying().(*types.Basic) maxType = expr.Max.Type().Underlying().(*types.Basic)
max = b.getValue(expr.Max) max = b.getValue(expr.Max, getPos(expr))
max = b.extendInteger(max, maxType, b.uintptrType) max = b.extendInteger(max, maxType, b.uintptrType)
} else { } else {
maxType = types.Typ[types.Uintptr] 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 // 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 // says. This requires a runtime check to make sure the slice is at
// least as big as the array. // least as big as the array.
slice := b.getValue(expr.X) slice := b.getValue(expr.X, getPos(expr))
sliceLen := b.CreateExtractValue(slice, 1, "") sliceLen := b.CreateExtractValue(slice, 1, "")
arrayLen := expr.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Array).Len() arrayLen := expr.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Array).Len()
b.createSliceToArrayPointerCheck(sliceLen, arrayLen) 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. // 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) { switch typ := expr.Type().Underlying().(type) {
case *types.Basic: case *types.Basic:
llvmType := c.getLLVMType(typ) llvmType := c.getLLVMType(typ)
@ -2860,15 +2860,15 @@ func (c *compilerContext) createConst(expr *ssa.Const) llvm.Value {
n, _ := constant.Float64Val(expr.Value) n, _ := constant.Float64Val(expr.Value)
return llvm.ConstFloat(llvmType, n) return llvm.ConstFloat(llvmType, n)
} else if typ.Kind() == types.Complex64 { } else if typ.Kind() == types.Complex64 {
r := c.createConst(ssa.NewConst(constant.Real(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])) 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 := 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, r, 0, "")
cplx = c.builder.CreateInsertValue(cplx, i, 1, "") cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
return cplx return cplx
} else if typ.Kind() == types.Complex128 { } else if typ.Kind() == types.Complex128 {
r := c.createConst(ssa.NewConst(constant.Real(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])) 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 := 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, r, 0, "")
cplx = c.builder.CreateInsertValue(cplx, i, 1, "") 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 // which can all be directly lowered to IR. However, there is also the channel
// receive operator which is handled in the runtime directly. // receive operator which is handled in the runtime directly.
func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) { 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 { switch unop.Op {
case token.NOT: // !x case token.NOT: // !x
return b.CreateNot(x, ""), nil return b.CreateNot(x, ""), nil

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

@ -267,13 +267,13 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// Collect all values to be put in the struct (starting with // Collect all values to be put in the struct (starting with
// runtime._defer fields, followed by the call parameters). // runtime._defer fields, followed by the call parameters).
itf := b.getValue(instr.Call.Value) // interface itf := b.getValue(instr.Call.Value, getPos(instr)) // interface
typecode := b.CreateExtractValue(itf, 0, "invoke.func.typecode") typecode := b.CreateExtractValue(itf, 0, "invoke.func.typecode")
receiverValue := b.CreateExtractValue(itf, 1, "invoke.func.receiver") receiverValue := b.CreateExtractValue(itf, 1, "invoke.func.receiver")
values = []llvm.Value{callback, next, typecode, receiverValue} values = []llvm.Value{callback, next, typecode, receiverValue}
valueTypes = append(valueTypes, b.i8ptrType, b.i8ptrType) valueTypes = append(valueTypes, b.i8ptrType, b.i8ptrType)
for _, arg := range instr.Call.Args { for _, arg := range instr.Call.Args {
val := b.getValue(arg) val := b.getValue(arg, getPos(instr))
values = append(values, val) values = append(values, val)
valueTypes = append(valueTypes, val.Type()) valueTypes = append(valueTypes, val.Type())
} }
@ -290,7 +290,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// runtime._defer fields). // runtime._defer fields).
values = []llvm.Value{callback, next} values = []llvm.Value{callback, next}
for _, param := range instr.Call.Args { for _, param := range instr.Call.Args {
llvmParam := b.getValue(param) llvmParam := b.getValue(param, getPos(instr))
values = append(values, llvmParam) values = append(values, llvmParam)
valueTypes = append(valueTypes, llvmParam.Type()) valueTypes = append(valueTypes, llvmParam.Type())
} }
@ -302,7 +302,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// pointer. // pointer.
// TODO: ignore this closure entirely and put pointers to the free // TODO: ignore this closure entirely and put pointers to the free
// variables directly in the defer struct, avoiding a memory allocation. // variables directly in the defer struct, avoiding a memory allocation.
closure := b.getValue(instr.Call.Value) closure := b.getValue(instr.Call.Value, getPos(instr))
context := b.CreateExtractValue(closure, 0, "") context := b.CreateExtractValue(closure, 0, "")
// Get the callback number. // Get the callback number.
@ -318,7 +318,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// context pointer). // context pointer).
values = []llvm.Value{callback, next} values = []llvm.Value{callback, next}
for _, param := range instr.Call.Args { for _, param := range instr.Call.Args {
llvmParam := b.getValue(param) llvmParam := b.getValue(param, getPos(instr))
values = append(values, llvmParam) values = append(values, llvmParam)
valueTypes = append(valueTypes, llvmParam.Type()) valueTypes = append(valueTypes, llvmParam.Type())
} }
@ -330,7 +330,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
var argValues []llvm.Value var argValues []llvm.Value
for _, arg := range instr.Call.Args { for _, arg := range instr.Call.Args {
argTypes = append(argTypes, arg.Type()) 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 { if _, ok := b.deferBuiltinFuncs[instr.Call.Value]; !ok {
@ -353,7 +353,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
} }
} else { } else {
funcValue := b.getValue(instr.Call.Value) funcValue := b.getValue(instr.Call.Value, getPos(instr))
if _, ok := b.deferExprFuncs[instr.Call.Value]; !ok { if _, ok := b.deferExprFuncs[instr.Call.Value]; !ok {
b.deferExprFuncs[instr.Call.Value] = len(b.allDeferFuncs) 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} values = []llvm.Value{callback, next, funcValue}
valueTypes = append(valueTypes, funcValue.Type()) valueTypes = append(valueTypes, funcValue.Type())
for _, param := range instr.Call.Args { for _, param := range instr.Call.Args {
llvmParam := b.getValue(param) llvmParam := b.getValue(param, getPos(instr))
values = append(values, llvmParam) values = append(values, llvmParam)
valueTypes = append(valueTypes, llvmParam.Type()) valueTypes = append(valueTypes, llvmParam.Type())
} }

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

@ -134,7 +134,7 @@ func (b *builder) parseMakeClosure(expr *ssa.MakeClosure) (llvm.Value, error) {
boundVars := make([]llvm.Value, len(expr.Bindings)) boundVars := make([]llvm.Value, len(expr.Bindings))
for i, binding := range expr.Bindings { for i, binding := range expr.Bindings {
// The context stores the bound variables. // The context stores the bound variables.
llvmBoundVar := b.getValue(binding) llvmBoundVar := b.getValue(binding, getPos(expr))
boundVars[i] = llvmBoundVar boundVars[i] = llvmBoundVar
} }

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

@ -16,7 +16,7 @@ func (b *builder) createGo(instr *ssa.Go) {
// Get all function parameters to pass to the goroutine. // Get all function parameters to pass to the goroutine.
var params []llvm.Value var params []llvm.Value
for _, param := range instr.Call.Args { for _, param := range instr.Call.Args {
params = append(params, b.getValue(param)) params = append(params, b.getValue(param, getPos(instr)))
} }
var prefix string var prefix string
@ -33,7 +33,7 @@ func (b *builder) createGo(instr *ssa.Go) {
case *ssa.MakeClosure: case *ssa.MakeClosure:
// A goroutine call on a func value, but the callee is trivial to find. For // A goroutine call on a func value, but the callee is trivial to find. For
// example: immediately applied functions. // example: immediately applied functions.
funcValue := b.getValue(value) funcValue := b.getValue(value, getPos(instr))
context = b.extractFuncContext(funcValue) context = b.extractFuncContext(funcValue)
default: default:
panic("StaticCallee returned an unexpected value") panic("StaticCallee returned an unexpected value")
@ -70,13 +70,13 @@ func (b *builder) createGo(instr *ssa.Go) {
var argValues []llvm.Value var argValues []llvm.Value
for _, arg := range instr.Call.Args { for _, arg := range instr.Call.Args {
argTypes = append(argTypes, arg.Type()) 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()) b.createBuiltin(argTypes, argValues, builtin.Name(), instr.Pos())
return return
} else if instr.Call.IsInvoke() { } else if instr.Call.IsInvoke() {
// This is a method call on an interface value. // 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, "") itfTypeCode := b.CreateExtractValue(itf, 0, "")
itfValue := b.CreateExtractValue(itf, 1, "") itfValue := b.CreateExtractValue(itf, 1, "")
funcPtr = b.getInvokeFunction(&instr.Call) funcPtr = b.getInvokeFunction(&instr.Call)
@ -90,7 +90,7 @@ func (b *builder) createGo(instr *ssa.Go) {
// * The function context, for closures. // * The function context, for closures.
// * The function pointer (for tasks). // * The function pointer (for tasks).
var context llvm.Value 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) params = append(params, context, funcPtr)
hasContext = true hasContext = true
prefix = b.fn.RelString(nil) prefix = b.fn.RelString(nil)

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

@ -5,6 +5,7 @@ package compiler
import ( import (
"fmt" "fmt"
"go/constant" "go/constant"
"go/token"
"regexp" "regexp"
"strconv" "strconv"
"strings" "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") 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) 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: case *ssa.Call:
if r.Common() == instr { if r.Common() == instr {
break 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 // The num parameter must be a constant. All other parameters may be any scalar
// value supported by LLVM inline assembly. // 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) num, _ := constant.Uint64Val(args[0].(*ssa.Const).Value)
llvmArgs := []llvm.Value{} llvmArgs := []llvm.Value{}
argTypes := []llvm.Type{} argTypes := []llvm.Type{}
@ -153,7 +154,7 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) {
} else { } else {
constraints += ",{r" + strconv.Itoa(i) + "}" constraints += ",{r" + strconv.Itoa(i) + "}"
} }
llvmValue := b.getValue(arg) llvmValue := b.getValue(arg, pos)
llvmArgs = append(llvmArgs, llvmValue) llvmArgs = append(llvmArgs, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) 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 // The num parameter must be a constant. All other parameters may be any scalar
// value supported by LLVM inline assembly. // value supported by LLVM inline assembly.
// Same as emitSVCall but for AArch64 // 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) num, _ := constant.Uint64Val(args[0].(*ssa.Const).Value)
llvmArgs := []llvm.Value{} llvmArgs := []llvm.Value{}
argTypes := []llvm.Type{} argTypes := []llvm.Type{}
@ -191,7 +192,7 @@ func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error) {
} else { } else {
constraints += ",{x" + strconv.Itoa(i) + "}" constraints += ",{x" + strconv.Itoa(i) + "}"
} }
llvmValue := b.getValue(arg) llvmValue := b.getValue(arg, pos)
llvmArgs = append(llvmArgs, llvmValue) llvmArgs = append(llvmArgs, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) 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) fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.uintptrType}, false)
asm := fmt.Sprintf("csrw %d, $0", csr) asm := fmt.Sprintf("csrw %d, $0", csr)
target := llvm.InlineAsm(fnType, asm, "r", true, false, 0, false) 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": case "SetBits":
// Note: it may be possible to optimize this to csrrsi in many cases. // Note: it may be possible to optimize this to csrrsi in many cases.
fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false) fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false)
asm := fmt.Sprintf("csrrs $0, %d, $1", csr) asm := fmt.Sprintf("csrrs $0, %d, $1", csr)
target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0, false) 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": case "ClearBits":
// Note: it may be possible to optimize this to csrrci in many cases. // Note: it may be possible to optimize this to csrrci in many cases.
fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false) fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false)
asm := fmt.Sprintf("csrrc $0, %d, $1", csr) asm := fmt.Sprintf("csrrc $0, %d, $1", csr)
target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0, false) 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: default:
return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation: "+name) return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation: "+name)
} }

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

@ -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 // Type asserts on concrete types are trivial: just compare type numbers. Type
// asserts on interfaces are more difficult, see the comments in the function. // asserts on interfaces are more difficult, see the comments in the function.
func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value { 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) assertedType := b.getLLVMType(expr.AssertedType)
actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type") actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type")

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

@ -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 // Note that bound functions are allowed if the function has a pointer
// receiver and is a global. This is rather strict but still allows for // receiver and is a global. This is rather strict but still allows for
// idiomatic Go code. // idiomatic Go code.
funcValue := b.getValue(instr.Args[1]) funcValue := b.getValue(instr.Args[1], getPos(instr))
if funcValue.IsAConstant().IsNil() { if funcValue.IsAConstant().IsNil() {
// Try to determine the cause of the non-constantness for a nice error // Try to determine the cause of the non-constantness for a nice error
// message. // message.

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

@ -58,7 +58,7 @@ func (b *builder) createMemoryCopyImpl() {
} }
var params []llvm.Value var params []llvm.Value
for _, param := range b.fn.Params { 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)) params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false))
b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "") b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "")
@ -80,9 +80,9 @@ func (b *builder) createMemoryZeroImpl() {
llvmFn = llvm.AddFunction(b.mod, fnName, fnType) llvmFn = llvm.AddFunction(b.mod, fnName, fnType)
} }
params := []llvm.Value{ 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), 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), llvm.ConstInt(b.ctx.Int1Type(), 0, false),
} }
b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "") b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "")
@ -95,7 +95,7 @@ func (b *builder) createKeepAliveImpl() {
b.createFunctionStart(true) b.createFunctionStart(true)
// Get the underlying value of the interface value. // 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, "") pointerValue := b.CreateExtractValue(interfaceValue, 1, "")
// Create an equivalent of the following C code, which is basically just a // 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. // Create a call to the intrinsic.
args := make([]llvm.Value, len(b.fn.Params)) args := make([]llvm.Value, len(b.fn.Params))
for i, param := range 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, "") result := b.CreateCall(llvmFn.GlobalValueType(), llvmFn, args, "")
b.CreateRet(result) b.CreateRet(result)

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

@ -46,7 +46,7 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
sizeHint := llvm.ConstInt(b.uintptrType, 8, false) sizeHint := llvm.ConstInt(b.uintptrType, 8, false)
algEnum := llvm.ConstInt(b.ctx.Int8Type(), alg, false) algEnum := llvm.ConstInt(b.ctx.Int8Type(), alg, false)
if expr.Reserve != nil { if expr.Reserve != nil {
sizeHint = b.getValue(expr.Reserve) sizeHint = b.getValue(expr.Reserve, getPos(expr))
var err error var err error
sizeHint, err = b.createConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos()) sizeHint, err = b.createConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos())
if err != nil { if err != nil {

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

@ -14,7 +14,7 @@ import (
// and returns the result as a single integer (the system call result). The // and returns the result as a single integer (the system call result). The
// result is not further interpreted. // result is not further interpreted.
func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { 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 { switch {
case b.GOARCH == "amd64" && b.GOOS == "linux": case b.GOARCH == "amd64" && b.GOOS == "linux":
// Sources: // Sources:
@ -37,7 +37,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
"{r12}", "{r12}",
"{r13}", "{r13}",
}[i] }[i]
llvmValue := b.getValue(arg) llvmValue := b.getValue(arg, getPos(call))
args = append(args, llvmValue) args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }
@ -64,7 +64,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
"{edi}", "{edi}",
"{ebp}", "{ebp}",
}[i] }[i]
llvmValue := b.getValue(arg) llvmValue := b.getValue(arg, getPos(call))
args = append(args, llvmValue) args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }
@ -89,7 +89,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
"{r5}", "{r5}",
"{r6}", "{r6}",
}[i] }[i]
llvmValue := b.getValue(arg) llvmValue := b.getValue(arg, getPos(call))
args = append(args, llvmValue) args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }
@ -119,7 +119,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
"{x4}", "{x4}",
"{x5}", "{x5}",
}[i] }[i]
llvmValue := b.getValue(arg) llvmValue := b.getValue(arg, getPos(call))
args = append(args, llvmValue) args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type()) argTypes = append(argTypes, llvmValue.Type())
} }
@ -177,12 +177,12 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
var paramTypes []llvm.Type var paramTypes []llvm.Type
var params []llvm.Value var params []llvm.Value
for _, val := range call.Args[2:] { for _, val := range call.Args[2:] {
param := b.getValue(val) param := b.getValue(val, getPos(call))
params = append(params, param) params = append(params, param)
paramTypes = append(paramTypes, param.Type()) paramTypes = append(paramTypes, param.Type())
} }
llvmType := llvm.FunctionType(b.uintptrType, paramTypes, false) 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), "") fnPtr := b.CreateIntToPtr(fn, llvm.PointerType(llvmType, 0), "")
// Prepare some functions that will be called later. // Prepare some functions that will be called later.

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

@ -9,7 +9,7 @@ import "go/types"
// runtime/volatile.LoadT(). // runtime/volatile.LoadT().
func (b *builder) createVolatileLoad() { func (b *builder) createVolatileLoad() {
b.createFunctionStart(true) 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") b.createNilCheck(b.fn.Params[0], addr, "deref")
valType := b.getLLVMType(b.fn.Params[0].Type().(*types.Pointer).Elem()) valType := b.getLLVMType(b.fn.Params[0].Type().(*types.Pointer).Elem())
val := b.CreateLoad(valType, addr, "") val := b.CreateLoad(valType, addr, "")
@ -21,8 +21,8 @@ func (b *builder) createVolatileLoad() {
// runtime/volatile.StoreT(). // runtime/volatile.StoreT().
func (b *builder) createVolatileStore() { func (b *builder) createVolatileStore() {
b.createFunctionStart(true) b.createFunctionStart(true)
addr := b.getValue(b.fn.Params[0]) addr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1]) val := b.getValue(b.fn.Params[1], getPos(b.fn))
b.createNilCheck(b.fn.Params[0], addr, "deref") b.createNilCheck(b.fn.Params[0], addr, "deref")
store := b.CreateStore(val, addr) store := b.CreateStore(val, addr)
store.SetVolatile(true) store.SetVolatile(true)