github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/compiler/alias.go (about)

     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 TinyGo 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 TinyGo (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  
    27  	// math package
    28  	"math.archHypot": "math.hypot",
    29  	"math.archMax":   "math.max",
    30  	"math.archMin":   "math.min",
    31  	"math.archModf":  "math.modf",
    32  }
    33  
    34  // createAlias implements the function (in the builder) as a call to the alias
    35  // function.
    36  func (b *builder) createAlias(alias llvm.Value) {
    37  	b.llvmFn.SetVisibility(llvm.HiddenVisibility)
    38  	b.llvmFn.SetUnnamedAddr(true)
    39  
    40  	if b.Debug {
    41  		if b.fn.Syntax() != nil {
    42  			// Create debug info file if present.
    43  			b.difunc = b.attachDebugInfo(b.fn)
    44  		}
    45  		pos := b.program.Fset.Position(b.fn.Pos())
    46  		b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
    47  	}
    48  	entryBlock := b.ctx.AddBasicBlock(b.llvmFn, "entry")
    49  	b.SetInsertPointAtEnd(entryBlock)
    50  	if b.llvmFn.Type() != alias.Type() {
    51  		b.addError(b.fn.Pos(), "alias function should have the same type as aliasee "+alias.Name())
    52  		b.CreateUnreachable()
    53  		return
    54  	}
    55  	result := b.CreateCall(alias.GlobalValueType(), alias, b.llvmFn.Params(), "")
    56  	if result.Type().TypeKind() == llvm.VoidTypeKind {
    57  		b.CreateRetVoid()
    58  	} else {
    59  		b.CreateRet(result)
    60  	}
    61  }