mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-21 12:59:04 +00:00
compiler: implement internal/abi.Escape
This commit is contained in:
committed by
Ron Evans
parent
5c46efb4d1
commit
34efc3a381
@@ -121,6 +121,29 @@ func (b *builder) createKeepAliveImpl() {
|
|||||||
b.CreateRetVoid()
|
b.CreateRetVoid()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createAbiEscapeImpl implements the generic internal/abi.Escape function. It
|
||||||
|
// currently only supports pointer types.
|
||||||
|
func (b *builder) createAbiEscapeImpl() {
|
||||||
|
b.createFunctionStart(true)
|
||||||
|
|
||||||
|
// The first parameter is assumed to be a pointer. This is checked at the
|
||||||
|
// call site of createAbiEscapeImpl.
|
||||||
|
pointerValue := b.getValue(b.fn.Params[0], getPos(b.fn))
|
||||||
|
|
||||||
|
// Create an equivalent of the following C code, which is basically just a
|
||||||
|
// nop but ensures the pointerValue is kept alive:
|
||||||
|
//
|
||||||
|
// __asm__ __volatile__("" : : "r"(pointerValue))
|
||||||
|
//
|
||||||
|
// It should be portable to basically everything as the "r" register type
|
||||||
|
// exists basically everywhere.
|
||||||
|
asmType := llvm.FunctionType(b.dataPtrType, []llvm.Type{b.dataPtrType}, false)
|
||||||
|
asmFn := llvm.InlineAsm(asmType, "", "=r,0", true, false, 0, false)
|
||||||
|
result := b.createCall(asmType, asmFn, []llvm.Value{pointerValue}, "")
|
||||||
|
|
||||||
|
b.CreateRet(result)
|
||||||
|
}
|
||||||
|
|
||||||
var mathToLLVMMapping = map[string]string{
|
var mathToLLVMMapping = map[string]string{
|
||||||
"math.Ceil": "llvm.ceil.f64",
|
"math.Ceil": "llvm.ceil.f64",
|
||||||
"math.Exp": "llvm.exp.f64",
|
"math.Exp": "llvm.exp.f64",
|
||||||
|
|||||||
@@ -253,6 +253,23 @@ func (c *compilerContext) maybeCreateSyntheticFunction(fn *ssa.Function, llvmFn
|
|||||||
// The exception is the package initializer, which does appear in the
|
// The exception is the package initializer, which does appear in the
|
||||||
// *ssa.Package members and so shouldn't be created here.
|
// *ssa.Package members and so shouldn't be created here.
|
||||||
if fn.Synthetic != "" && fn.Synthetic != "package initializer" && fn.Synthetic != "generic function" && fn.Synthetic != "range-over-func yield" {
|
if fn.Synthetic != "" && fn.Synthetic != "package initializer" && fn.Synthetic != "generic function" && fn.Synthetic != "range-over-func yield" {
|
||||||
|
if origin := fn.Origin(); origin != nil && origin.RelString(nil) == "internal/abi.Escape" {
|
||||||
|
// This is a special implementation or internal/abi.Escape, which
|
||||||
|
// can only really be implemented in the compiler.
|
||||||
|
// For simplicity we'll only implement pointer parameters for now.
|
||||||
|
if _, ok := fn.Params[0].Type().Underlying().(*types.Pointer); ok {
|
||||||
|
irbuilder := c.ctx.NewBuilder()
|
||||||
|
defer irbuilder.Dispose()
|
||||||
|
b := newBuilder(c, irbuilder, fn)
|
||||||
|
b.createAbiEscapeImpl()
|
||||||
|
llvmFn.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||||
|
llvmFn.SetUnnamedAddr(true)
|
||||||
|
}
|
||||||
|
// If the parameter is not of a pointer type, it will be left
|
||||||
|
// unimplemented. This will result in a linker error if the function
|
||||||
|
// is really called, making it clear it needs to be implemented.
|
||||||
|
return
|
||||||
|
}
|
||||||
if len(fn.Blocks) == 0 {
|
if len(fn.Blocks) == 0 {
|
||||||
c.addError(fn.Pos(), "missing function body")
|
c.addError(fn.Pos(), "missing function body")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -8,3 +8,10 @@ import "unsafe"
|
|||||||
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Escape[T any](x T) T {
|
||||||
|
// This function is either implemented in the compiler, or left undefined
|
||||||
|
// for some variation of T. The body of this function should not be compiled
|
||||||
|
// as-is.
|
||||||
|
panic("internal/abi.Escape: unreachable (implemented in the compiler)")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user