all: add type parameter to CreateCall
This uses LLVMBuildCall2 in the background, which is the replacement for the deprecated LLVMBuildCall function.
Этот коммит содержится в:
родитель
b79bf29c11
коммит
6bc6de8f82
26 изменённых файлов: 123 добавлений и 103 удалений
|
@ -516,7 +516,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||
if pkgInit.IsNil() {
|
||||
panic("init not found for " + pkg.Pkg.Path())
|
||||
}
|
||||
irbuilder.CreateCall(pkgInit, []llvm.Value{llvm.Undef(i8ptrType)}, "")
|
||||
irbuilder.CreateCall(pkgInit.GlobalValueType(), pkgInit, []llvm.Value{llvm.Undef(i8ptrType)}, "")
|
||||
}
|
||||
irbuilder.CreateRetVoid()
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ func (b *builder) createAlias(alias llvm.Value) {
|
|||
b.CreateUnreachable()
|
||||
return
|
||||
}
|
||||
result := b.CreateCall(alias, b.llvmFn.Params(), "")
|
||||
result := b.CreateCall(alias.GlobalValueType(), alias, b.llvmFn.Params(), "")
|
||||
if result.Type().TypeKind() == llvm.VoidTypeKind {
|
||||
b.CreateRetVoid()
|
||||
} else {
|
||||
|
|
|
@ -25,7 +25,7 @@ func (b *builder) createAtomicOp(name string) llvm.Value {
|
|||
if fn.IsNil() {
|
||||
fn = llvm.AddFunction(b.mod, name, llvm.FunctionType(vType, []llvm.Type{ptr.Type(), vType}, false))
|
||||
}
|
||||
oldVal := b.createCall(fn, []llvm.Value{ptr, val}, "")
|
||||
oldVal := b.createCall(fn.GlobalValueType(), fn, []llvm.Value{ptr, val}, "")
|
||||
// Return the new value, not the original value returned.
|
||||
return b.CreateAdd(oldVal, val, "")
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ func (b *builder) createAtomicOp(name string) llvm.Value {
|
|||
if fn.IsNil() {
|
||||
fn = llvm.AddFunction(b.mod, name, llvm.FunctionType(vType, []llvm.Type{ptr.Type(), vType, b.uintptrType}, false))
|
||||
}
|
||||
b.createCall(fn, []llvm.Value{ptr, val, llvm.ConstInt(b.uintptrType, 5, false)}, "")
|
||||
b.createCall(fn.GlobalValueType(), fn, []llvm.Value{ptr, val, llvm.ConstInt(b.uintptrType, 5, false)}, "")
|
||||
return llvm.Value{}
|
||||
}
|
||||
store := b.CreateStore(val, ptr)
|
||||
|
|
|
@ -37,15 +37,15 @@ const (
|
|||
// createRuntimeInvoke instead.
|
||||
func (b *builder) createRuntimeCallCommon(fnName string, args []llvm.Value, name string, isInvoke bool) llvm.Value {
|
||||
fn := b.program.ImportedPackage("runtime").Members[fnName].(*ssa.Function)
|
||||
llvmFn := b.getFunction(fn)
|
||||
fnType, llvmFn := b.getFunction(fn)
|
||||
if llvmFn.IsNil() {
|
||||
panic("trying to call non-existent function: " + fn.RelString(nil))
|
||||
}
|
||||
args = append(args, llvm.Undef(b.i8ptrType)) // unused context parameter
|
||||
if isInvoke {
|
||||
return b.createInvoke(llvmFn, args, name)
|
||||
return b.createInvoke(fnType, llvmFn, args, name)
|
||||
}
|
||||
return b.createCall(llvmFn, args, name)
|
||||
return b.createCall(fnType, llvmFn, args, name)
|
||||
}
|
||||
|
||||
// createRuntimeCall creates a new call to runtime.<fnName> with the given
|
||||
|
@ -65,22 +65,22 @@ func (b *builder) createRuntimeInvoke(fnName string, args []llvm.Value, name str
|
|||
|
||||
// createCall creates a call to the given function with the arguments possibly
|
||||
// expanded.
|
||||
func (b *builder) createCall(fn llvm.Value, args []llvm.Value, name string) llvm.Value {
|
||||
func (b *builder) createCall(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
|
||||
expanded := make([]llvm.Value, 0, len(args))
|
||||
for _, arg := range args {
|
||||
fragments := b.expandFormalParam(arg)
|
||||
expanded = append(expanded, fragments...)
|
||||
}
|
||||
return b.CreateCall(fn, expanded, name)
|
||||
return b.CreateCall(fnType, fn, expanded, name)
|
||||
}
|
||||
|
||||
// createInvoke is like createCall but continues execution at the landing pad if
|
||||
// the call resulted in a panic.
|
||||
func (b *builder) createInvoke(fn llvm.Value, args []llvm.Value, name string) llvm.Value {
|
||||
func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
|
||||
if b.hasDeferFrame() {
|
||||
b.createInvokeCheckpoint()
|
||||
}
|
||||
return b.createCall(fn, args, name)
|
||||
return b.createCall(fnType, fn, args, name)
|
||||
}
|
||||
|
||||
// Expand an argument type to a list that can be used in a function call
|
||||
|
|
|
@ -131,6 +131,7 @@ type builder struct {
|
|||
*compilerContext
|
||||
llvm.Builder
|
||||
fn *ssa.Function
|
||||
llvmFnType llvm.Type
|
||||
llvmFn llvm.Value
|
||||
info functionInfo
|
||||
locals map[ssa.Value]llvm.Value // local variables
|
||||
|
@ -155,11 +156,13 @@ type builder struct {
|
|||
}
|
||||
|
||||
func newBuilder(c *compilerContext, irbuilder llvm.Builder, f *ssa.Function) *builder {
|
||||
fnType, fn := c.getFunction(f)
|
||||
return &builder{
|
||||
compilerContext: c,
|
||||
Builder: irbuilder,
|
||||
fn: f,
|
||||
llvmFn: c.getFunction(f),
|
||||
llvmFnType: fnType,
|
||||
llvmFn: fn,
|
||||
info: c.getFunctionInfo(f),
|
||||
locals: make(map[ssa.Value]llvm.Value),
|
||||
dilocals: make(map[*types.Var]llvm.Metadata),
|
||||
|
@ -711,7 +714,8 @@ func (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata {
|
|||
// DISubprogram metadata node.
|
||||
func (c *compilerContext) attachDebugInfo(f *ssa.Function) llvm.Metadata {
|
||||
pos := c.program.Fset.Position(f.Syntax().Pos())
|
||||
return c.attachDebugInfoRaw(f, c.getFunction(f), "", pos.Filename, pos.Line)
|
||||
_, fn := c.getFunction(f)
|
||||
return c.attachDebugInfoRaw(f, fn, "", pos.Filename, pos.Line)
|
||||
}
|
||||
|
||||
// attachDebugInfo adds debug info to a function declaration. It returns the
|
||||
|
@ -1654,6 +1658,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||
|
||||
// Try to call the function directly for trivially static calls.
|
||||
var callee, context llvm.Value
|
||||
var calleeType llvm.Type
|
||||
exported := false
|
||||
if fn := instr.StaticCallee(); fn != nil {
|
||||
// Direct function call, either to a named or anonymous (directly
|
||||
|
@ -1684,7 +1689,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||
return b.createInterruptGlobal(instr)
|
||||
}
|
||||
|
||||
callee = b.getFunction(fn)
|
||||
calleeType, callee = b.getFunction(fn)
|
||||
info := b.getFunctionInfo(fn)
|
||||
if callee.IsNil() {
|
||||
return llvm.Value{}, b.makeError(instr.Pos(), "undefined function: "+info.linkName)
|
||||
|
@ -1698,8 +1703,8 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||
// Eventually we might be able to eliminate this special case
|
||||
// entirely. For details, see:
|
||||
// https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521
|
||||
fnType := llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false)
|
||||
callee = llvm.ConstBitCast(callee, llvm.PointerType(fnType, b.funcPtrAddrSpace))
|
||||
calleeType = llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false)
|
||||
callee = llvm.ConstBitCast(callee, llvm.PointerType(calleeType, b.funcPtrAddrSpace))
|
||||
}
|
||||
case *ssa.MakeClosure:
|
||||
// A call on a func value, but the callee is trivial to find. For
|
||||
|
@ -1726,13 +1731,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||
params = append([]llvm.Value{value}, params...)
|
||||
params = append(params, typecode)
|
||||
callee = b.getInvokeFunction(instr)
|
||||
calleeType = callee.GlobalValueType()
|
||||
context = llvm.Undef(b.i8ptrType)
|
||||
} else {
|
||||
// Function pointer.
|
||||
value := b.getValue(instr.Value)
|
||||
// This is a func value, which cannot be called directly. We have to
|
||||
// extract the function pointer and context first from the func value.
|
||||
callee, context = b.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature))
|
||||
calleeType, callee, context = b.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature))
|
||||
b.createNilCheck(instr.Value, callee, "fpcall")
|
||||
}
|
||||
|
||||
|
@ -1742,7 +1748,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||
params = append(params, context)
|
||||
}
|
||||
|
||||
return b.createInvoke(callee, params, ""), nil
|
||||
return b.createInvoke(calleeType, callee, params, ""), nil
|
||||
}
|
||||
|
||||
// getValue returns the LLVM value of a constant, function value, global, or
|
||||
|
@ -1756,7 +1762,8 @@ func (b *builder) getValue(expr ssa.Value) llvm.Value {
|
|||
b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String())
|
||||
return llvm.Undef(b.getLLVMType(expr.Type()))
|
||||
}
|
||||
return b.createFuncValue(b.getFunction(expr), llvm.Undef(b.i8ptrType), expr.Signature)
|
||||
_, fn := b.getFunction(expr)
|
||||
return b.createFuncValue(fn, llvm.Undef(b.i8ptrType), expr.Signature)
|
||||
case *ssa.Global:
|
||||
value := b.getGlobal(expr)
|
||||
if value.IsNil() {
|
||||
|
@ -3080,7 +3087,7 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
|
|||
// Instead of a load from the global, create a bitcast of the
|
||||
// function pointer itself.
|
||||
name := strings.TrimSuffix(unop.X.(*ssa.Global).Name(), "$funcaddr")
|
||||
fn := b.getFunction(b.fn.Pkg.Members[name].(*ssa.Function))
|
||||
_, fn := b.getFunction(b.fn.Pkg.Members[name].(*ssa.Function))
|
||||
if fn.IsNil() {
|
||||
return llvm.Value{}, b.makeError(unop.Pos(), "cgo function not found: "+name)
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ li a0, 0
|
|||
}
|
||||
asmType := llvm.FunctionType(resultType, []llvm.Type{b.deferFrame.Type()}, false)
|
||||
asm := llvm.InlineAsm(asmType, asmString, constraints, false, false, 0, false)
|
||||
result := b.CreateCall(asm, []llvm.Value{b.deferFrame}, "setjmp")
|
||||
result := b.CreateCall(asmType, asm, []llvm.Value{b.deferFrame}, "setjmp")
|
||||
result.AddCallSiteAttribute(-1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("returns_twice"), 0))
|
||||
isZero := b.CreateICmp(llvm.IntEQ, result, llvm.ConstInt(resultType, 0, false), "setjmp.result")
|
||||
continueBB := b.insertBasicBlock("")
|
||||
|
@ -492,6 +492,7 @@ func (b *builder) createRunDefers() {
|
|||
}
|
||||
|
||||
var fnPtr llvm.Value
|
||||
var fnType llvm.Type
|
||||
|
||||
if !callback.IsInvoke() {
|
||||
// Isolate the func value.
|
||||
|
@ -499,8 +500,8 @@ func (b *builder) createRunDefers() {
|
|||
forwardParams = forwardParams[1:]
|
||||
|
||||
//Get function pointer and context
|
||||
fp, context := b.decodeFuncValue(funcValue, callback.Signature())
|
||||
fnPtr = fp
|
||||
var context llvm.Value
|
||||
fnType, fnPtr, context = b.decodeFuncValue(funcValue, callback.Signature())
|
||||
|
||||
//Pass context
|
||||
forwardParams = append(forwardParams, context)
|
||||
|
@ -509,6 +510,7 @@ func (b *builder) createRunDefers() {
|
|||
// parameters.
|
||||
forwardParams = append(forwardParams[1:], forwardParams[0])
|
||||
fnPtr = b.getInvokeFunction(callback)
|
||||
fnType = fnPtr.GlobalValueType()
|
||||
|
||||
// Add the context parameter. An interface call cannot also be a
|
||||
// closure but we have to supply the parameter anyway for platforms
|
||||
|
@ -516,7 +518,7 @@ func (b *builder) createRunDefers() {
|
|||
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
|
||||
}
|
||||
|
||||
b.createCall(fnPtr, forwardParams, "")
|
||||
b.createCall(fnType, fnPtr, forwardParams, "")
|
||||
|
||||
case *ssa.Function:
|
||||
// Direct call.
|
||||
|
@ -547,7 +549,8 @@ func (b *builder) createRunDefers() {
|
|||
}
|
||||
|
||||
// Call real function.
|
||||
b.createInvoke(b.getFunction(callback), forwardParams, "")
|
||||
fnType, fn := b.getFunction(callback)
|
||||
b.createInvoke(fnType, fn, forwardParams, "")
|
||||
|
||||
case *ssa.MakeClosure:
|
||||
// Get the real defer struct type and cast to it.
|
||||
|
@ -571,7 +574,8 @@ func (b *builder) createRunDefers() {
|
|||
}
|
||||
|
||||
// Call deferred function.
|
||||
b.createCall(b.getFunction(fn), forwardParams, "")
|
||||
fnType, llvmFn := b.getFunction(fn)
|
||||
b.createCall(fnType, llvmFn, forwardParams, "")
|
||||
case *ssa.Builtin:
|
||||
db := b.deferBuiltinFuncs[callback]
|
||||
|
||||
|
|
|
@ -55,14 +55,15 @@ func (b *builder) extractFuncContext(funcValue llvm.Value) llvm.Value {
|
|||
|
||||
// decodeFuncValue extracts the context and the function pointer from this func
|
||||
// value. This may be an expensive operation.
|
||||
func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcPtr, context llvm.Value) {
|
||||
func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcType llvm.Type, funcPtr, context llvm.Value) {
|
||||
context = b.CreateExtractValue(funcValue, 0, "")
|
||||
bitcast := b.CreateExtractValue(funcValue, 1, "")
|
||||
if !bitcast.IsAConstantExpr().IsNil() && bitcast.Opcode() == llvm.BitCast {
|
||||
funcPtr = bitcast.Operand(0)
|
||||
return
|
||||
}
|
||||
llvmSig := llvm.PointerType(b.getRawFuncType(sig), b.funcPtrAddrSpace)
|
||||
funcType = b.getRawFuncType(sig)
|
||||
llvmSig := llvm.PointerType(funcType, b.funcPtrAddrSpace)
|
||||
funcPtr = b.CreateBitCast(bitcast, llvmSig, "")
|
||||
return
|
||||
}
|
||||
|
@ -141,5 +142,6 @@ func (b *builder) parseMakeClosure(expr *ssa.MakeClosure) (llvm.Value, error) {
|
|||
context := b.emitPointerPack(boundVars)
|
||||
|
||||
// Create the closure.
|
||||
return b.createFuncValue(b.getFunction(f), context, f.Signature), nil
|
||||
_, fn := b.getFunction(f)
|
||||
return b.createFuncValue(fn, context, f.Signature), nil
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||
|
||||
var prefix string
|
||||
var funcPtr llvm.Value
|
||||
var funcPtrType llvm.Type
|
||||
hasContext := false
|
||||
if callee := instr.Call.StaticCallee(); callee != nil {
|
||||
// Static callee is known. This makes it easier to start a new
|
||||
|
@ -42,7 +43,7 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||
params = append(params, context) // context parameter
|
||||
hasContext = true
|
||||
}
|
||||
funcPtr = b.getFunction(callee)
|
||||
funcPtrType, funcPtr = b.getFunction(callee)
|
||||
} else if builtin, ok := instr.Call.Value.(*ssa.Builtin); ok {
|
||||
// We cheat. None of the builtins do any long or blocking operation, so
|
||||
// we might as well run these builtins right away without the program
|
||||
|
@ -80,6 +81,7 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||
itfTypeCode := b.CreateExtractValue(itf, 0, "")
|
||||
itfValue := b.CreateExtractValue(itf, 1, "")
|
||||
funcPtr = b.getInvokeFunction(&instr.Call)
|
||||
funcPtrType = funcPtr.GlobalValueType()
|
||||
params = append([]llvm.Value{itfValue}, params...) // start with receiver
|
||||
params = append(params, itfTypeCode) // end with typecode
|
||||
} else {
|
||||
|
@ -89,7 +91,7 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||
// * The function context, for closures.
|
||||
// * The function pointer (for tasks).
|
||||
var context llvm.Value
|
||||
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), instr.Call.Value.Type().Underlying().(*types.Signature))
|
||||
params = append(params, context, funcPtr)
|
||||
hasContext = true
|
||||
prefix = b.fn.RelString(nil)
|
||||
|
@ -97,14 +99,14 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||
|
||||
paramBundle := b.emitPointerPack(params)
|
||||
var stackSize llvm.Value
|
||||
callee := b.createGoroutineStartWrapper(funcPtr, prefix, hasContext, instr.Pos())
|
||||
callee := b.createGoroutineStartWrapper(funcPtrType, funcPtr, prefix, hasContext, instr.Pos())
|
||||
if b.AutomaticStackSize {
|
||||
// The stack size is not known until after linking. Call a dummy
|
||||
// function that will be replaced with a load from a special ELF
|
||||
// section that contains the stack size (and is modified after
|
||||
// linking).
|
||||
stackSizeFn := b.getFunction(b.program.ImportedPackage("internal/task").Members["getGoroutineStackSize"].(*ssa.Function))
|
||||
stackSize = b.createCall(stackSizeFn, []llvm.Value{callee, llvm.Undef(b.i8ptrType)}, "stacksize")
|
||||
stackSizeFnType, stackSizeFn := b.getFunction(b.program.ImportedPackage("internal/task").Members["getGoroutineStackSize"].(*ssa.Function))
|
||||
stackSize = b.createCall(stackSizeFnType, stackSizeFn, []llvm.Value{callee, llvm.Undef(b.i8ptrType)}, "stacksize")
|
||||
} else {
|
||||
// The stack size is fixed at compile time. By emitting it here as a
|
||||
// constant, it can be optimized.
|
||||
|
@ -113,8 +115,8 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||
}
|
||||
stackSize = llvm.ConstInt(b.uintptrType, b.DefaultStackSize, false)
|
||||
}
|
||||
start := b.getFunction(b.program.ImportedPackage("internal/task").Members["start"].(*ssa.Function))
|
||||
b.createCall(start, []llvm.Value{callee, paramBundle, stackSize, llvm.Undef(b.i8ptrType)}, "")
|
||||
fnType, start := b.getFunction(b.program.ImportedPackage("internal/task").Members["start"].(*ssa.Function))
|
||||
b.createCall(fnType, start, []llvm.Value{callee, paramBundle, stackSize, llvm.Undef(b.i8ptrType)}, "")
|
||||
}
|
||||
|
||||
// createGoroutineStartWrapper creates a wrapper for the task-based
|
||||
|
@ -140,15 +142,16 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||
// to last parameter of the function) is used for this wrapper. If hasContext is
|
||||
// false, the parameter bundle is assumed to have no context parameter and undef
|
||||
// is passed instead.
|
||||
func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix string, hasContext bool, pos token.Pos) llvm.Value {
|
||||
func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.Value, prefix string, hasContext bool, pos token.Pos) llvm.Value {
|
||||
var wrapper llvm.Value
|
||||
|
||||
builder := c.ctx.NewBuilder()
|
||||
defer builder.Dispose()
|
||||
|
||||
var deadlock llvm.Value
|
||||
var deadlockType llvm.Type
|
||||
if c.Scheduler == "asyncify" {
|
||||
deadlock = c.getFunction(c.program.ImportedPackage("runtime").Members["deadlock"].(*ssa.Function))
|
||||
deadlockType, deadlock = c.getFunction(c.program.ImportedPackage("runtime").Members["deadlock"].(*ssa.Function))
|
||||
}
|
||||
|
||||
if !fn.IsAFunction().IsNil() {
|
||||
|
@ -192,7 +195,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
|
|||
}
|
||||
|
||||
// Create the list of params for the call.
|
||||
paramTypes := fn.Type().ElementType().ParamTypes()
|
||||
paramTypes := fnType.ParamTypes()
|
||||
if !hasContext {
|
||||
paramTypes = paramTypes[:len(paramTypes)-1] // strip context parameter
|
||||
}
|
||||
|
@ -202,10 +205,10 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
|
|||
}
|
||||
|
||||
// Create the call.
|
||||
builder.CreateCall(fn, params, "")
|
||||
builder.CreateCall(fnType, fn, params, "")
|
||||
|
||||
if c.Scheduler == "asyncify" {
|
||||
builder.CreateCall(deadlock, []llvm.Value{
|
||||
builder.CreateCall(deadlockType, deadlock, []llvm.Value{
|
||||
llvm.Undef(c.i8ptrType),
|
||||
}, "")
|
||||
}
|
||||
|
@ -261,7 +264,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
|
|||
}
|
||||
|
||||
// Get the list of parameters, with the extra parameters at the end.
|
||||
paramTypes := fn.Type().ElementType().ParamTypes()
|
||||
paramTypes := fnType.ParamTypes()
|
||||
paramTypes = append(paramTypes, fn.Type()) // the last element is the function pointer
|
||||
params := llvmutil.EmitPointerUnpack(builder, c.mod, wrapper.Param(0), paramTypes)
|
||||
|
||||
|
@ -270,10 +273,10 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
|
|||
params = params[:len(params)-1]
|
||||
|
||||
// Create the call.
|
||||
builder.CreateCall(fnPtr, params, "")
|
||||
builder.CreateCall(fnType, fnPtr, params, "")
|
||||
|
||||
if c.Scheduler == "asyncify" {
|
||||
builder.CreateCall(deadlock, []llvm.Value{
|
||||
builder.CreateCall(deadlockType, deadlock, []llvm.Value{
|
||||
llvm.Undef(c.i8ptrType),
|
||||
}, "")
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
|
|||
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{}, false)
|
||||
asm := constant.StringVal(args[0].(*ssa.Const).Value)
|
||||
target := llvm.InlineAsm(fnType, asm, "", true, false, 0, false)
|
||||
return b.CreateCall(target, nil, ""), nil
|
||||
return b.CreateCall(fnType, target, nil, ""), nil
|
||||
}
|
||||
|
||||
// This is a compiler builtin, which allows assembly to be called in a flexible
|
||||
|
@ -120,7 +120,7 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error)
|
|||
}
|
||||
fnType := llvm.FunctionType(outputType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, asmString, strings.Join(constraints, ","), true, false, 0, false)
|
||||
result := b.CreateCall(target, args, "")
|
||||
result := b.CreateCall(fnType, target, args, "")
|
||||
if hasOutput {
|
||||
return result, nil
|
||||
} else {
|
||||
|
@ -163,7 +163,7 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) {
|
|||
constraints += ",~{r1},~{r2},~{r3}"
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)
|
||||
return b.CreateCall(target, llvmArgs, ""), nil
|
||||
return b.CreateCall(fnType, target, llvmArgs, ""), nil
|
||||
}
|
||||
|
||||
// This is a compiler builtin which emits an inline SVCall instruction. It can
|
||||
|
@ -201,7 +201,7 @@ func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error) {
|
|||
constraints += ",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}"
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)
|
||||
return b.CreateCall(target, llvmArgs, ""), nil
|
||||
return b.CreateCall(fnType, target, llvmArgs, ""), nil
|
||||
}
|
||||
|
||||
// This is a compiler builtin which emits CSR instructions. It can be one of:
|
||||
|
@ -226,24 +226,24 @@ func (b *builder) emitCSROperation(call *ssa.CallCommon) (llvm.Value, error) {
|
|||
fnType := llvm.FunctionType(b.uintptrType, nil, false)
|
||||
asm := fmt.Sprintf("csrr $0, %d", csr)
|
||||
target := llvm.InlineAsm(fnType, asm, "=r", true, false, 0, false)
|
||||
return b.CreateCall(target, nil, ""), nil
|
||||
return b.CreateCall(fnType, target, nil, ""), nil
|
||||
case "Set":
|
||||
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(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil
|
||||
return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), 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(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil
|
||||
return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), 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(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil
|
||||
return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil
|
||||
default:
|
||||
return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation: "+name)
|
||||
}
|
||||
|
|
|
@ -254,12 +254,12 @@ func (c *compilerContext) getTypeMethodSet(typ types.Type) llvm.Value {
|
|||
method := ms.At(i)
|
||||
signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))
|
||||
fn := c.program.MethodValue(method)
|
||||
llvmFn := c.getFunction(fn)
|
||||
llvmFnType, llvmFn := c.getFunction(fn)
|
||||
if llvmFn.IsNil() {
|
||||
// compiler error, so panic
|
||||
panic("cannot find function: " + c.getFunctionInfo(fn).linkName)
|
||||
}
|
||||
wrapper := c.getInterfaceInvokeWrapper(fn, llvmFn)
|
||||
wrapper := c.getInterfaceInvokeWrapper(fn, llvmFnType, llvmFn)
|
||||
methodInfo := llvm.ConstNamedStruct(interfaceMethodInfoType, []llvm.Value{
|
||||
signatureGlobal,
|
||||
llvm.ConstPtrToInt(wrapper, c.uintptrType),
|
||||
|
@ -361,7 +361,7 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
|
|||
// implements each method of the interface. See:
|
||||
// https://research.swtch.com/interfaces
|
||||
fn := b.getInterfaceImplementsFunc(expr.AssertedType)
|
||||
commaOk = b.CreateCall(fn, []llvm.Value{actualTypeNum}, "")
|
||||
commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, "")
|
||||
|
||||
} else {
|
||||
globalName := "reflect/types.typeid:" + getTypeCodeName(expr.AssertedType)
|
||||
|
@ -480,7 +480,7 @@ func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon) llvm.Value {
|
|||
// value, dereferences or unpacks it if necessary, and calls the real method.
|
||||
// If the method to wrap has a pointer receiver, no wrapping is necessary and
|
||||
// the function is returned directly.
|
||||
func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llvm.Value) llvm.Value {
|
||||
func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFnType llvm.Type, llvmFn llvm.Value) llvm.Value {
|
||||
wrapperName := llvmFn.Name() + "$invoke"
|
||||
wrapper := c.mod.NamedFunction(wrapperName)
|
||||
if !wrapper.IsNil() {
|
||||
|
@ -505,9 +505,8 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llv
|
|||
}
|
||||
|
||||
// create wrapper function
|
||||
fnType := llvmFn.Type().ElementType()
|
||||
paramTypes := append([]llvm.Type{c.i8ptrType}, fnType.ParamTypes()[len(expandedReceiverType):]...)
|
||||
wrapFnType := llvm.FunctionType(fnType.ReturnType(), paramTypes, false)
|
||||
paramTypes := append([]llvm.Type{c.i8ptrType}, llvmFnType.ParamTypes()[len(expandedReceiverType):]...)
|
||||
wrapFnType := llvm.FunctionType(llvmFnType.ReturnType(), paramTypes, false)
|
||||
wrapper = llvm.AddFunction(c.mod, wrapperName, wrapFnType)
|
||||
c.addStandardAttributes(wrapper)
|
||||
|
||||
|
@ -535,10 +534,10 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llv
|
|||
receiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0]
|
||||
params := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...)
|
||||
if llvmFn.Type().ElementType().ReturnType().TypeKind() == llvm.VoidTypeKind {
|
||||
b.CreateCall(llvmFn, params, "")
|
||||
b.CreateCall(llvmFnType, llvmFn, params, "")
|
||||
b.CreateRetVoid()
|
||||
} else {
|
||||
ret := b.CreateCall(llvmFn, params, "ret")
|
||||
ret := b.CreateCall(llvmFnType, llvmFn, params, "ret")
|
||||
b.CreateRet(ret)
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro
|
|||
// Fall back to a generic error.
|
||||
return llvm.Value{}, b.makeError(instr.Pos(), "interrupt function must be constant")
|
||||
}
|
||||
funcRawPtr, funcContext := b.decodeFuncValue(funcValue, nil)
|
||||
_, funcRawPtr, funcContext := b.decodeFuncValue(funcValue, nil)
|
||||
funcPtr := llvm.ConstPtrToInt(funcRawPtr, b.uintptrType)
|
||||
|
||||
// Create a new global of type runtime/interrupt.handle. Globals of this
|
||||
|
@ -85,7 +85,7 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro
|
|||
useFnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{interrupt.Type()}, false)
|
||||
useFn = llvm.AddFunction(b.mod, "runtime/interrupt.use", useFnType)
|
||||
}
|
||||
b.CreateCall(useFn, []llvm.Value{interrupt}, "")
|
||||
b.CreateCall(useFn.GlobalValueType(), useFn, []llvm.Value{interrupt}, "")
|
||||
}
|
||||
|
||||
return interrupt, nil
|
||||
|
|
|
@ -55,7 +55,7 @@ func (b *builder) createMemoryCopyImpl() {
|
|||
params = append(params, b.getValue(param))
|
||||
}
|
||||
params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false))
|
||||
b.CreateCall(llvmFn, params, "")
|
||||
b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "")
|
||||
b.CreateRetVoid()
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ func (b *builder) createMemoryZeroImpl() {
|
|||
b.getValue(b.fn.Params[1]),
|
||||
llvm.ConstInt(b.ctx.Int1Type(), 0, false),
|
||||
}
|
||||
b.CreateCall(llvmFn, params, "")
|
||||
b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "")
|
||||
b.CreateRetVoid()
|
||||
}
|
||||
|
||||
|
@ -119,6 +119,6 @@ func (b *builder) defineMathOp() {
|
|||
for i, param := range b.fn.Params {
|
||||
args[i] = b.getValue(param)
|
||||
}
|
||||
result := b.CreateCall(llvmFn, args, "")
|
||||
result := b.CreateCall(llvmFn.GlobalValueType(), llvmFn, args, "")
|
||||
b.CreateRet(result)
|
||||
}
|
||||
|
|
|
@ -312,5 +312,5 @@ func (b *builder) readStackPointer() llvm.Value {
|
|||
fnType := llvm.FunctionType(b.i8ptrType, nil, false)
|
||||
stacksave = llvm.AddFunction(b.mod, "llvm.stacksave", fnType)
|
||||
}
|
||||
return b.CreateCall(stacksave, nil, "")
|
||||
return b.CreateCall(stacksave.GlobalValueType(), stacksave, nil, "")
|
||||
}
|
||||
|
|
|
@ -39,7 +39,8 @@ func CreateTemporaryAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, n
|
|||
alloca = CreateEntryBlockAlloca(builder, t, name)
|
||||
bitcast = builder.CreateBitCast(alloca, i8ptrType, name+".bitcast")
|
||||
size = llvm.ConstInt(ctx.Int64Type(), targetData.TypeAllocSize(t), false)
|
||||
builder.CreateCall(getLifetimeStartFunc(mod), []llvm.Value{size, bitcast}, "")
|
||||
fnType, fn := getLifetimeStartFunc(mod)
|
||||
builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -54,13 +55,15 @@ func CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type,
|
|||
builder.SetInsertPointBefore(inst)
|
||||
bitcast := builder.CreateBitCast(alloca, i8ptrType, name+".bitcast")
|
||||
size := llvm.ConstInt(ctx.Int64Type(), targetData.TypeAllocSize(t), false)
|
||||
builder.CreateCall(getLifetimeStartFunc(mod), []llvm.Value{size, bitcast}, "")
|
||||
fnType, fn := getLifetimeStartFunc(mod)
|
||||
builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "")
|
||||
if next := llvm.NextInstruction(inst); !next.IsNil() {
|
||||
builder.SetInsertPointBefore(next)
|
||||
} else {
|
||||
builder.SetInsertPointAtEnd(inst.InstructionParent())
|
||||
}
|
||||
builder.CreateCall(getLifetimeEndFunc(mod), []llvm.Value{size, bitcast}, "")
|
||||
fnType, fn = getLifetimeEndFunc(mod)
|
||||
builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "")
|
||||
return alloca
|
||||
}
|
||||
|
||||
|
@ -68,33 +71,34 @@ func CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type,
|
|||
// llvm.lifetime.end intrinsic. It is commonly used together with
|
||||
// createTemporaryAlloca.
|
||||
func EmitLifetimeEnd(builder llvm.Builder, mod llvm.Module, ptr, size llvm.Value) {
|
||||
builder.CreateCall(getLifetimeEndFunc(mod), []llvm.Value{size, ptr}, "")
|
||||
fnType, fn := getLifetimeEndFunc(mod)
|
||||
builder.CreateCall(fnType, fn, []llvm.Value{size, ptr}, "")
|
||||
}
|
||||
|
||||
// getLifetimeStartFunc returns the llvm.lifetime.start intrinsic and creates it
|
||||
// first if it doesn't exist yet.
|
||||
func getLifetimeStartFunc(mod llvm.Module) llvm.Value {
|
||||
func getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
|
||||
fn := mod.NamedFunction("llvm.lifetime.start.p0i8")
|
||||
ctx := mod.Context()
|
||||
i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
|
||||
if fn.IsNil() {
|
||||
fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false)
|
||||
if fn.IsNil() {
|
||||
fn = llvm.AddFunction(mod, "llvm.lifetime.start.p0i8", fnType)
|
||||
}
|
||||
return fn
|
||||
return fnType, fn
|
||||
}
|
||||
|
||||
// getLifetimeEndFunc returns the llvm.lifetime.end intrinsic and creates it
|
||||
// first if it doesn't exist yet.
|
||||
func getLifetimeEndFunc(mod llvm.Module) llvm.Value {
|
||||
func getLifetimeEndFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
|
||||
fn := mod.NamedFunction("llvm.lifetime.end.p0i8")
|
||||
ctx := mod.Context()
|
||||
i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
|
||||
if fn.IsNil() {
|
||||
fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false)
|
||||
if fn.IsNil() {
|
||||
fn = llvm.AddFunction(mod, "llvm.lifetime.end.p0i8", fnType)
|
||||
}
|
||||
return fn
|
||||
return fnType, fn
|
||||
}
|
||||
|
||||
// SplitBasicBlock splits a LLVM basic block into two parts. All instructions
|
||||
|
|
|
@ -95,14 +95,14 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix string, needs
|
|||
// Packed data is bigger than a pointer, so allocate it on the heap.
|
||||
sizeValue := llvm.ConstInt(uintptrType, size, false)
|
||||
alloc := mod.NamedFunction("runtime.alloc")
|
||||
packedHeapAlloc := builder.CreateCall(alloc, []llvm.Value{
|
||||
packedHeapAlloc := builder.CreateCall(alloc.GlobalValueType(), alloc, []llvm.Value{
|
||||
sizeValue,
|
||||
llvm.ConstNull(i8ptrType),
|
||||
llvm.Undef(i8ptrType), // unused context parameter
|
||||
}, "")
|
||||
if needsStackObjects {
|
||||
trackPointer := mod.NamedFunction("runtime.trackPointer")
|
||||
builder.CreateCall(trackPointer, []llvm.Value{
|
||||
builder.CreateCall(trackPointer.GlobalValueType(), trackPointer, []llvm.Value{
|
||||
packedHeapAlloc,
|
||||
llvm.Undef(i8ptrType), // unused context parameter
|
||||
}, "")
|
||||
|
|
|
@ -53,11 +53,11 @@ const (
|
|||
|
||||
// getFunction returns the LLVM function for the given *ssa.Function, creating
|
||||
// it if needed. It can later be filled with compilerContext.createFunction().
|
||||
func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
|
||||
func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) {
|
||||
info := c.getFunctionInfo(fn)
|
||||
llvmFn := c.mod.NamedFunction(info.linkName)
|
||||
if !llvmFn.IsNil() {
|
||||
return llvmFn
|
||||
return llvmFn.GlobalValueType(), llvmFn
|
||||
}
|
||||
|
||||
var retType llvm.Type
|
||||
|
@ -202,7 +202,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
|
|||
llvmFn.SetUnnamedAddr(true)
|
||||
}
|
||||
|
||||
return llvmFn
|
||||
return fnType, llvmFn
|
||||
}
|
||||
|
||||
// getFunctionInfo returns information about a function that is not directly
|
||||
|
|
|
@ -44,7 +44,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||
constraints += ",~{rcx},~{r11}"
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel, false)
|
||||
return b.CreateCall(target, args, ""), nil
|
||||
return b.CreateCall(fnType, target, args, ""), nil
|
||||
case b.GOARCH == "386" && b.GOOS == "linux":
|
||||
// Sources:
|
||||
// syscall(2) man page
|
||||
|
@ -70,7 +70,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||
}
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel, false)
|
||||
return b.CreateCall(target, args, ""), nil
|
||||
return b.CreateCall(fnType, target, args, ""), nil
|
||||
case b.GOARCH == "arm" && b.GOOS == "linux":
|
||||
// Implement the EABI system call convention for Linux.
|
||||
// Source: syscall(2) man page.
|
||||
|
@ -102,7 +102,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||
}
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
|
||||
return b.CreateCall(target, args, ""), nil
|
||||
return b.CreateCall(fnType, target, args, ""), nil
|
||||
case b.GOARCH == "arm64" && b.GOOS == "linux":
|
||||
// Source: syscall(2) man page.
|
||||
args := []llvm.Value{}
|
||||
|
@ -134,7 +134,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||
constraints += ",~{x16},~{x17}" // scratch registers
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
|
||||
return b.CreateCall(target, args, ""), nil
|
||||
return b.CreateCall(fnType, target, args, ""), nil
|
||||
default:
|
||||
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
|
||||
}
|
||||
|
@ -205,9 +205,9 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||
// Note that SetLastError/GetLastError could be replaced with direct
|
||||
// access to the thread control block, which is probably smaller and
|
||||
// faster. The Go runtime does this in assembly.
|
||||
b.CreateCall(setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, "")
|
||||
syscallResult := b.CreateCall(fnPtr, params, "")
|
||||
errResult := b.CreateCall(getLastError, nil, "err")
|
||||
b.CreateCall(setLastError.GlobalValueType(), setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, "")
|
||||
syscallResult := b.CreateCall(llvmType, fnPtr, params, "")
|
||||
errResult := b.CreateCall(getLastError.GlobalValueType(), getLastError, nil, "err")
|
||||
if b.uintptrType != b.ctx.Int32Type() {
|
||||
errResult = b.CreateZExt(errResult, b.uintptrType, "err.uintptr")
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -17,7 +17,7 @@ require (
|
|||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
||||
golang.org/x/tools v0.1.11
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7
|
||||
tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
4
go.sum
4
go.sum
|
@ -64,5 +64,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636 h1:JxtI6P/lyWHAcs/4QJWeWIbh4HntxPFONMVWvx7wf8Y=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
|
|
|
@ -127,7 +127,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
|
|||
// Create a call to the package initializer (which was
|
||||
// previously deleted).
|
||||
i8undef := llvm.Undef(r.i8ptrType)
|
||||
r.builder.CreateCall(fn, []llvm.Value{i8undef}, "")
|
||||
r.builder.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{i8undef}, "")
|
||||
// Make sure that any globals touched by the package
|
||||
// initializer, won't be accessed by later package initializers.
|
||||
err := r.markExternalLoad(fn)
|
||||
|
|
|
@ -977,7 +977,7 @@ func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, me
|
|||
}
|
||||
}
|
||||
}
|
||||
result = r.builder.CreateCall(llvmFn, args, inst.name)
|
||||
result = r.builder.CreateCall(inst.llvmInst.CalledFunctionType(), llvmFn, args, inst.name)
|
||||
case llvm.Load:
|
||||
err := mem.markExternalLoad(operands[0])
|
||||
if err != nil {
|
||||
|
|
|
@ -493,12 +493,13 @@ func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *inte
|
|||
paramTypes = append(paramTypes, param.Type())
|
||||
}
|
||||
calledFunctionType := function.Type()
|
||||
sig := llvm.PointerType(llvm.FunctionType(returnType, paramTypes, false), calledFunctionType.PointerAddressSpace())
|
||||
functionType := llvm.FunctionType(returnType, paramTypes, false)
|
||||
sig := llvm.PointerType(functionType, calledFunctionType.PointerAddressSpace())
|
||||
if sig != function.Type() {
|
||||
function = p.builder.CreateBitCast(function, sig, "")
|
||||
}
|
||||
|
||||
retval := p.builder.CreateCall(function, append([]llvm.Value{receiver}, params...), "")
|
||||
retval := p.builder.CreateCall(functionType, function, append([]llvm.Value{receiver}, params...), "")
|
||||
if retval.Type().TypeKind() == llvm.VoidTypeKind {
|
||||
p.builder.CreateRetVoid()
|
||||
} else {
|
||||
|
@ -518,7 +519,7 @@ func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *inte
|
|||
// importantly, it avoids undefined behavior when accidentally calling a
|
||||
// method on a nil interface.
|
||||
nilPanic := p.mod.NamedFunction("runtime.nilPanic")
|
||||
p.builder.CreateCall(nilPanic, []llvm.Value{
|
||||
p.builder.CreateCall(nilPanic.GlobalValueType(), nilPanic, []llvm.Value{
|
||||
llvm.Undef(llvm.PointerType(p.ctx.Int8Type(), 0)),
|
||||
}, "")
|
||||
p.builder.CreateUnreachable()
|
||||
|
|
|
@ -91,7 +91,7 @@ func LowerInterrupts(mod llvm.Module) []error {
|
|||
initializer := handler.Initializer()
|
||||
context := llvm.ConstExtractValue(initializer, []uint32{0})
|
||||
funcPtr := llvm.ConstExtractValue(initializer, []uint32{1}).Operand(0)
|
||||
builder.CreateCall(funcPtr, []llvm.Value{
|
||||
builder.CreateCall(funcPtr.GlobalValueType(), funcPtr, []llvm.Value{
|
||||
num,
|
||||
context,
|
||||
}, "")
|
||||
|
|
|
@ -27,7 +27,7 @@ func ReplacePanicsWithTrap(mod llvm.Module) {
|
|||
panic("expected use of a panic function to be a call")
|
||||
}
|
||||
builder.SetInsertPointBefore(use)
|
||||
builder.CreateCall(trap, nil, "")
|
||||
builder.CreateCall(trap.GlobalValueType(), trap, nil, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ func OptimizeReflectImplements(mod llvm.Module) {
|
|||
|
||||
// Replace Implements call with the type assert call.
|
||||
builder.SetInsertPointBefore(call)
|
||||
implements := builder.CreateCall(typeAssertFunction, []llvm.Value{
|
||||
implements := builder.CreateCall(typeAssertFunction.GlobalValueType(), typeAssertFunction, []llvm.Value{
|
||||
builder.CreatePtrToInt(call.Operand(0), uintptrType, ""), // typecode to check
|
||||
}, "")
|
||||
call.ReplaceAllUsesWith(implements)
|
||||
|
|
|
@ -124,12 +124,12 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config) error {
|
|||
// Pass a stack-allocated pointer as the first parameter
|
||||
// where the return value should be stored, instead of using
|
||||
// the regular return value.
|
||||
builder.CreateCall(externalFn, callParams, callName)
|
||||
builder.CreateCall(externalFnType, externalFn, callParams, callName)
|
||||
returnValue := builder.CreateLoad(retvalAlloca, "retval")
|
||||
call.ReplaceAllUsesWith(returnValue)
|
||||
call.EraseFromParentAsInstruction()
|
||||
} else {
|
||||
newCall := builder.CreateCall(externalFn, callParams, callName)
|
||||
newCall := builder.CreateCall(externalFnType, externalFn, callParams, callName)
|
||||
call.ReplaceAllUsesWith(newCall)
|
||||
call.EraseFromParentAsInstruction()
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config) error {
|
|||
}
|
||||
callParams = append(callParams, paramValue)
|
||||
}
|
||||
retval := builder.CreateCall(fn, callParams, "")
|
||||
retval := builder.CreateCall(fn.GlobalValueType(), fn, callParams, "")
|
||||
if retval.Type().TypeKind() == llvm.VoidTypeKind {
|
||||
builder.CreateRetVoid()
|
||||
} else {
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче