77 "strconv"
88 "strings"
99
10+ "github.com/tinygo-org/tinygo/compiler/llvmutil"
1011 "tinygo.org/x/go-llvm"
1112)
1213
@@ -166,12 +167,22 @@ func (b *builder) createMachineKeepAliveImpl() {
166167}
167168
168169var mathToLLVMMapping = map [string ]string {
170+ "math.Acos" : "llvm.acos.f64" ,
171+ "math.Asin" : "llvm.asin.f64" ,
172+ "math.Atan" : "llvm.atan.f64" ,
173+ "math.Atan2" : "llvm.atan2.f64" ,
169174 "math.Ceil" : "llvm.ceil.f64" ,
175+ "math.Cos" : "llvm.cos.f64" ,
176+ "math.Cosh" : "llvm.cosh.f64" ,
170177 "math.Exp" : "llvm.exp.f64" ,
171178 "math.Exp2" : "llvm.exp2.f64" ,
172179 "math.Floor" : "llvm.floor.f64" ,
173180 "math.Log" : "llvm.log.f64" ,
181+ "math.Sin" : "llvm.sin.f64" ,
182+ "math.Sinh" : "llvm.sinh.f64" ,
174183 "math.Sqrt" : "llvm.sqrt.f64" ,
184+ "math.Tan" : "llvm.tan.f64" ,
185+ "math.Tanh" : "llvm.tanh.f64" ,
175186 "math.Trunc" : "llvm.trunc.f64" ,
176187}
177188
@@ -185,18 +196,40 @@ var mathToLLVMMapping = map[string]string{
185196// float32(math.Sqrt(float64(v))) to a 32-bit floating point operation, which is
186197// beneficial on architectures where 64-bit floating point operations are (much)
187198// more expensive than 32-bit ones.
188- func (b * builder ) defineMathOp () {
189- b .createFunctionStart (true )
190- llvmName := mathToLLVMMapping [b .fn .RelString (nil )]
191- if llvmName == "" {
192- panic ("unreachable: unknown math operation" ) // sanity check
199+ func (b * builder ) defineMathOp () bool {
200+ llvmName , ok := mathToLLVMMapping [b .fn .RelString (nil )]
201+ if ! ok {
202+ return false
203+ }
204+ if strings .HasSuffix (b .Triple , "-wasi" ) || llvmutil .Version () < 19 {
205+ // We don't have a real libc for wasip2. Until that is fixed, we need to
206+ // limit math intrinsics on WASI to a subset supported natively in
207+ // WebAssembly.
208+ // Also, since we don't know the specific libc we will target, disallow
209+ // these for all WASI targets.
210+ //
211+ // We also need to limit ourselves to LLVM 19 and above for the extended
212+ // set of math intrinsics, see:
213+ // https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294
214+ switch b .fn .Name () {
215+ case "Ceil" , "Exp" , "Exp2" , "Floor" , "Log" , "Sqrt" , "Trunc" :
216+ default :
217+ return false
218+ }
193219 }
220+ b .createFunctionStart (true )
194221 llvmFn := b .mod .NamedFunction (llvmName )
195222 if llvmFn .IsNil () {
196223 // The intrinsic doesn't exist yet, so declare it.
197- // At the moment, all supported intrinsics have the form "double
198- // foo(double %x)" so we can hardcode the signature here.
199- llvmType := llvm .FunctionType (b .ctx .DoubleType (), []llvm.Type {b .ctx .DoubleType ()}, false )
224+ var llvmType llvm.Type
225+ switch b .fn .Name () {
226+ case "Atan2" :
227+ // double atan2(double %y, double %x)
228+ llvmType = llvm .FunctionType (b .ctx .DoubleType (), []llvm.Type {b .ctx .DoubleType (), b .ctx .DoubleType ()}, false )
229+ default :
230+ // double foo(double %x)
231+ llvmType = llvm .FunctionType (b .ctx .DoubleType (), []llvm.Type {b .ctx .DoubleType ()}, false )
232+ }
200233 llvmFn = llvm .AddFunction (b .mod , llvmName , llvmType )
201234 }
202235 // Create a call to the intrinsic.
@@ -206,6 +239,7 @@ func (b *builder) defineMathOp() {
206239 }
207240 result := b .CreateCall (llvmFn .GlobalValueType (), llvmFn , args , "" )
208241 b .CreateRet (result )
242+ return true
209243}
210244
211245func (b * builder ) defineCryptoIntrinsic () bool {
0 commit comments