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.Cos": "math.cos", "math.Cosh": "math.cosh", "math.Erf": "math.erf", "math.Erfc": "math.erfc", "math.Exp": "math.exp", "math.Expm1": "math.expm1", "math.Exp2": "math.exp2", "math.Floor": "math.floor", "math.Frexp": "math.frexp", "math.Hypot": "math.hypot", "math.Ldexp": "math.ldexp", "math.Log": "math.log", "math.Log1p": "math.log1p", "math.Log10": "math.log10", "math.Log2": "math.log2", "math.Max": "math.max", "math.Min": "math.min", "math.Mod": "math.mod", "math.Modf": "math.modf", "math.Pow": "math.pow", "math.Remainder": "math.remainder", "math.Sin": "math.sin", "math.Sinh": "math.sinh", "math.Sqrt": "math.sqrt", "math.Tan": "math.tan", "math.Tanh": "math.tanh", "math.Trunc": "math.trunc", } // createAlias implements the function (in the builder) as a call to the alias // function. func (b *builder) createAlias(alias llvm.Value) { 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 := llvm.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) } }