alias.go raw

   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