
llvm.AddBasicBlock should never be used. Instead, we should use the AddBasicBlock method of the current LLVM context. This didn't lead to any bugs... yet. But probably would, eventually.
102 строки
3,4 КиБ
Go
102 строки
3,4 КиБ
Go
package compiler
|
|
|
|
// This file defines alias functions for functions that are normally defined in
|
|
// Go assembly.
|
|
//
|
|
// The Go toolchain defines many performance critical functions in assembly
|
|
// instead of plain Go. This is a problem for TinyGo as it currently (as of
|
|
// august 2021) is not able to compile these assembly files and even if it
|
|
// could, it would not be able to make use of them for many targets that are
|
|
// supported by TinyGo (baremetal RISC-V, AVR, etc). Therefore, many of these
|
|
// functions are aliased to their generic Go implementation.
|
|
// This results in slower than possible implementations, but at least they are
|
|
// usable.
|
|
|
|
import "tinygo.org/x/go-llvm"
|
|
|
|
var stdlibAliases = map[string]string{
|
|
// crypto packages
|
|
"crypto/md5.block": "crypto/md5.blockGeneric",
|
|
"crypto/sha1.block": "crypto/sha1.blockGeneric",
|
|
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
|
|
"crypto/sha256.block": "crypto/sha256.blockGeneric",
|
|
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
|
|
|
|
// math package
|
|
"math.Asin": "math.asin",
|
|
"math.Asinh": "math.asinh",
|
|
"math.Acos": "math.acos",
|
|
"math.Acosh": "math.acosh",
|
|
"math.Atan": "math.atan",
|
|
"math.Atanh": "math.atanh",
|
|
"math.Atan2": "math.atan2",
|
|
"math.Cbrt": "math.cbrt",
|
|
"math.Ceil": "math.ceil",
|
|
"math.archCeil": "math.ceil",
|
|
"math.Cos": "math.cos",
|
|
"math.Cosh": "math.cosh",
|
|
"math.Erf": "math.erf",
|
|
"math.Erfc": "math.erfc",
|
|
"math.Exp": "math.exp",
|
|
"math.archExp": "math.exp",
|
|
"math.Expm1": "math.expm1",
|
|
"math.Exp2": "math.exp2",
|
|
"math.archExp2": "math.exp2",
|
|
"math.Floor": "math.floor",
|
|
"math.archFloor": "math.floor",
|
|
"math.Frexp": "math.frexp",
|
|
"math.Hypot": "math.hypot",
|
|
"math.archHypot": "math.hypot",
|
|
"math.Ldexp": "math.ldexp",
|
|
"math.Log": "math.log",
|
|
"math.archLog": "math.log",
|
|
"math.Log1p": "math.log1p",
|
|
"math.Log10": "math.log10",
|
|
"math.Log2": "math.log2",
|
|
"math.Max": "math.max",
|
|
"math.archMax": "math.max",
|
|
"math.Min": "math.min",
|
|
"math.archMin": "math.min",
|
|
"math.Mod": "math.mod",
|
|
"math.Modf": "math.modf",
|
|
"math.archModf": "math.modf",
|
|
"math.Pow": "math.pow",
|
|
"math.Remainder": "math.remainder",
|
|
"math.Sin": "math.sin",
|
|
"math.Sinh": "math.sinh",
|
|
"math.Sqrt": "math.sqrt",
|
|
"math.archSqrt": "math.sqrt",
|
|
"math.Tan": "math.tan",
|
|
"math.Tanh": "math.tanh",
|
|
"math.Trunc": "math.trunc",
|
|
"math.archTrunc": "math.trunc",
|
|
}
|
|
|
|
// createAlias implements the function (in the builder) as a call to the alias
|
|
// function.
|
|
func (b *builder) createAlias(alias llvm.Value) {
|
|
b.llvmFn.SetVisibility(llvm.HiddenVisibility)
|
|
b.llvmFn.SetUnnamedAddr(true)
|
|
|
|
if b.Debug {
|
|
if b.fn.Syntax() != nil {
|
|
// Create debug info file if present.
|
|
b.difunc = b.attachDebugInfo(b.fn)
|
|
}
|
|
pos := b.program.Fset.Position(b.fn.Pos())
|
|
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
|
|
}
|
|
entryBlock := b.ctx.AddBasicBlock(b.llvmFn, "entry")
|
|
b.SetInsertPointAtEnd(entryBlock)
|
|
if b.llvmFn.Type() != alias.Type() {
|
|
b.addError(b.fn.Pos(), "alias function should have the same type as aliasee "+alias.Name())
|
|
b.CreateUnreachable()
|
|
return
|
|
}
|
|
result := b.CreateCall(alias, b.llvmFn.Params(), "")
|
|
if result.Type().TypeKind() == llvm.VoidTypeKind {
|
|
b.CreateRetVoid()
|
|
} else {
|
|
b.CreateRet(result)
|
|
}
|
|
}
|