1 package compiler
2 3 // This file defines alias functions for functions that are normally defined in
4 // Go assembly.
5 //
6 // The Go toolchain defines many performance critical functions in assembly
7 // instead of plain Go. This is a problem for Moxie as it currently (as of
8 // august 2021) is not able to compile these assembly files and even if it
9 // could, it would not be able to make use of them for many targets that are
10 // supported by Moxie (baremetal RISC-V, AVR, etc). Therefore, many of these
11 // functions are aliased to their generic Go implementation.
12 // This results in slower than possible implementations, but at least they are
13 // usable.
14 15 import "tinygo.org/x/go-llvm"
16 17 var stdlibAliases = map[string]string{
18 // crypto packages
19 "crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric",
20 "crypto/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric",
21 "crypto/md5.block": "crypto/md5.blockGeneric",
22 "crypto/sha1.block": "crypto/sha1.blockGeneric",
23 "crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
24 "crypto/sha256.block": "crypto/sha256.blockGeneric",
25 "crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
26 "internal/chacha8rand.block": "internal/chacha8rand.block_generic",
27 28 // AES
29 "crypto/aes.decryptBlockAsm": "crypto/aes.decryptBlock",
30 "crypto/aes.encryptBlockAsm": "crypto/aes.encryptBlock",
31 32 // math package
33 "math.archHypot": "math.hypot",
34 "math.archMax": "math.max",
35 "math.archMin": "math.min",
36 "math.archModf": "math.modf",
37 }
38 39 // createAlias implements the function (in the builder) as a call to the alias
40 // function.
41 func (b *builder) createAlias(alias llvm.Value) {
42 b.llvmFn.SetVisibility(llvm.HiddenVisibility)
43 b.llvmFn.SetUnnamedAddr(true)
44 45 if b.Debug {
46 if b.fn.Syntax() != nil {
47 // Create debug info file if present.
48 b.difunc = b.attachDebugInfo(b.fn)
49 }
50 pos := b.program.Fset.Position(b.fn.Pos())
51 b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
52 }
53 entryBlock := b.ctx.AddBasicBlock(b.llvmFn, "entry")
54 b.SetInsertPointAtEnd(entryBlock)
55 if b.llvmFn.Type() != alias.Type() {
56 b.addError(b.fn.Pos(), "alias function should have the same type as aliasee "+alias.Name())
57 b.CreateUnreachable()
58 return
59 }
60 result := b.CreateCall(alias.GlobalValueType(), alias, b.llvmFn.Params(), "")
61 if result.Type().TypeKind() == llvm.VoidTypeKind {
62 b.CreateRetVoid()
63 } else {
64 b.CreateRet(result)
65 }
66 }
67