diff --git a/ir/passes.go b/ir/passes.go index e73bf34c..a3666474 100644 --- a/ir/passes.go +++ b/ir/passes.go @@ -68,10 +68,11 @@ func (p *Program) SimpleDCE() { // functions. main := p.mainPkg.Members["main"].(*ssa.Function) runtimePkg := p.Program.ImportedPackage("runtime") + mathPkg := p.Program.ImportedPackage("math") p.GetFunction(main).flag = true worklist := []*ssa.Function{main} for _, f := range p.Functions { - if f.exported || f.Synthetic == "package initializer" || f.Pkg == runtimePkg { + if f.exported || f.Synthetic == "package initializer" || f.Pkg == runtimePkg || (f.Pkg == mathPkg && f.Pkg != nil) { if f.flag || isCGoInternal(f.Name()) { continue } diff --git a/src/runtime/math.go b/src/runtime/math.go new file mode 100644 index 00000000..73af1591 --- /dev/null +++ b/src/runtime/math.go @@ -0,0 +1,224 @@ +package runtime + +// This file redirects math stubs to their fallback implementation. +// TODO: use optimized versions if possible. + +import ( + _ "unsafe" +) + +//go:linkname math_Asin math.Asin +func math_Asin(x float64) float64 { return math_asin(x) } + +//go:linkname math_asin math.asin +func math_asin(x float64) float64 + +//go:linkname math_Asinh math.Asinh +func math_Asinh(x float64) float64 { return math_asinh(x) } + +//go:linkname math_asinh math.asinh +func math_asinh(x float64) float64 + +//go:linkname math_Acos math.Acos +func math_Acos(x float64) float64 { return math_acos(x) } + +//go:linkname math_acos math.acos +func math_acos(x float64) float64 + +//go:linkname math_Acosh math.Acosh +func math_Acosh(x float64) float64 { return math_acosh(x) } + +//go:linkname math_acosh math.acosh +func math_acosh(x float64) float64 + +//go:linkname math_Atan math.Atan +func math_Atan(x float64) float64 { return math_atan(x) } + +//go:linkname math_atan math.atan +func math_atan(x float64) float64 + +//go:linkname math_Atanh math.Atanh +func math_Atanh(x float64) float64 { return math_atanh(x) } + +//go:linkname math_atanh math.atanh +func math_atanh(x float64) float64 + +//go:linkname math_Atan2 math.Atan2 +func math_Atan2(y, x float64) float64 { return math_atan2(y, x) } + +//go:linkname math_atan2 math.atan2 +func math_atan2(y, x float64) float64 + +//go:linkname math_Cbrt math.Cbrt +func math_Cbrt(x float64) float64 { return math_cbrt(x) } + +//go:linkname math_cbrt math.cbrt +func math_cbrt(x float64) float64 + +//go:linkname math_Ceil math.Ceil +func math_Ceil(x float64) float64 { return math_ceil(x) } + +//go:linkname math_ceil math.ceil +func math_ceil(x float64) float64 + +//go:linkname math_Cos math.Cos +func math_Cos(x float64) float64 { return math_cos(x) } + +//go:linkname math_cos math.cos +func math_cos(x float64) float64 + +//go:linkname math_Cosh math.Cosh +func math_Cosh(x float64) float64 { return math_cosh(x) } + +//go:linkname math_cosh math.cosh +func math_cosh(x float64) float64 + +//go:linkname math_Erf math.Erf +func math_Erf(x float64) float64 { return math_erf(x) } + +//go:linkname math_erf math.erf +func math_erf(x float64) float64 + +//go:linkname math_Erfc math.Erfc +func math_Erfc(x float64) float64 { return math_erfc(x) } + +//go:linkname math_erfc math.erfc +func math_erfc(x float64) float64 + +//go:linkname math_Exp math.Exp +func math_Exp(x float64) float64 { return math_exp(x) } + +//go:linkname math_exp math.exp +func math_exp(x float64) float64 + +//go:linkname math_Expm1 math.Expm1 +func math_Expm1(x float64) float64 { return math_expm1(x) } + +//go:linkname math_expm1 math.expm1 +func math_expm1(x float64) float64 + +//go:linkname math_Exp2 math.Exp2 +func math_Exp2(x float64) float64 { return math_exp2(x) } + +//go:linkname math_exp2 math.exp2 +func math_exp2(x float64) float64 + +//go:linkname math_Floor math.Floor +func math_Floor(x float64) float64 { return math_floor(x) } + +//go:linkname math_floor math.floor +func math_floor(x float64) float64 + +//go:linkname math_Frexp math.Frexp +func math_Frexp(x float64) (float64, int) { return math_frexp(x) } + +//go:linkname math_frexp math.frexp +func math_frexp(x float64) (float64, int) + +//go:linkname math_Hypot math.Hypot +func math_Hypot(p, q float64) float64 { return math_hypot(p, q) } + +//go:linkname math_hypot math.hypot +func math_hypot(p, q float64) float64 + +//go:linkname math_Ldexp math.Ldexp +func math_Ldexp(frac float64, exp int) float64 { return math_ldexp(frac, exp) } + +//go:linkname math_ldexp math.ldexp +func math_ldexp(frac float64, exp int) float64 + +//go:linkname math_Log math.Log +func math_Log(x float64) float64 { return math_log(x) } + +//go:linkname math_log math.log +func math_log(x float64) float64 + +//go:linkname math_Log1p math.Log1p +func math_Log1p(x float64) float64 { return math_log1p(x) } + +//go:linkname math_log1p math.log1p +func math_log1p(x float64) float64 + +//go:linkname math_Log10 math.Log10 +func math_Log10(x float64) float64 { return math_log10(x) } + +//go:linkname math_log10 math.log10 +func math_log10(x float64) float64 + +//go:linkname math_Log2 math.Log2 +func math_Log2(x float64) float64 { return math_log2(x) } + +//go:linkname math_log2 math.log2 +func math_log2(x float64) float64 + +//go:linkname math_Max math.Max +func math_Max(x, y float64) float64 { return math_max(x, y) } + +//go:linkname math_max math.max +func math_max(x, y float64) float64 + +//go:linkname math_Min math.Min +func math_Min(x, y float64) float64 { return math_min(x, y) } + +//go:linkname math_min math.min +func math_min(x, y float64) float64 + +//go:linkname math_Mod math.Mod +func math_Mod(x, y float64) float64 { return math_mod(x, y) } + +//go:linkname math_mod math.mod +func math_mod(x, y float64) float64 + +//go:linkname math_Modf math.Modf +func math_Modf(x float64) (float64, float64) { return math_modf(x) } + +//go:linkname math_modf math.modf +func math_modf(x float64) (float64, float64) + +//go:linkname math_Pow math.Pow +func math_Pow(x, y float64) float64 { return math_pow(x, y) } + +//go:linkname math_pow math.pow +func math_pow(x, y float64) float64 + +//go:linkname math_Remainder math.Remainder +func math_Remainder(x, y float64) float64 { return math_remainder(x, y) } + +//go:linkname math_remainder math.remainder +func math_remainder(x, y float64) float64 + +//go:linkname math_Sin math.Sin +func math_Sin(x float64) float64 { return math_sin(x) } + +//go:linkname math_sin math.sin +func math_sin(x float64) float64 + +//go:linkname math_Sinh math.Sinh +func math_Sinh(x float64) float64 { return math_sinh(x) } + +//go:linkname math_sinh math.sinh +func math_sinh(x float64) float64 + +//go:linkname math_Sqrt math.Sqrt +func math_Sqrt(x float64) float64 { return math_sqrt(x) } + +//go:linkname math_sqrt math.sqrt +func math_sqrt(x float64) float64 + +//go:linkname math_Tan math.Tan +func math_Tan(x float64) float64 { return math_tan(x) } + +//go:linkname math_tan math.tan +func math_tan(x float64) float64 + +//go:linkname math_Tanh math.Tanh +func math_Tanh(x float64) float64 { return math_tanh(x) } + +//go:linkname math_tanh math.tanh +func math_tanh(x float64) float64 + +//go:linkname math_Trunc math.Trunc +func math_Trunc(x float64) float64 { return math_trunc(x) } + +//go:linkname math_trunc math.trunc +func math_trunc(x float64) float64 diff --git a/testdata/math.go b/testdata/math.go new file mode 100644 index 00000000..eceb39f3 --- /dev/null +++ b/testdata/math.go @@ -0,0 +1,46 @@ +package main + +import "math" + +func main() { + for _, n := range []float64{0.3, 1.5, 2.6, -1.1, -3.1, -3.8} { + println("n:", n) + println(" asin: ", math.Asin(n)) + println(" asinh: ", math.Asinh(n)) + println(" acos: ", math.Acos(n)) + println(" acosh: ", math.Acosh(n)) + println(" atan: ", math.Atan(n)) + println(" atanh: ", math.Atanh(n)) + println(" atan2: ", math.Atan2(n, 0.2)) + println(" cbrt: ", math.Cbrt(n)) + println(" ceil: ", math.Ceil(n)) + println(" cos: ", math.Cos(n)) + println(" cosh: ", math.Cosh(n)) + println(" erf: ", math.Erf(n)) + println(" erfc: ", math.Erfc(n)) + println(" exp: ", math.Exp(n)) + println(" expm1: ", math.Expm1(n)) + println(" exp2: ", math.Exp2(n)) + println(" floor: ", math.Floor(n)) + f, e := math.Frexp(n) + println(" frexp: ", f, e) + println(" hypot: ", math.Hypot(n, n*2)) + println(" ldexp: ", math.Ldexp(n, 2)) + println(" log: ", math.Log(n)) + println(" log1p: ", math.Log1p(n)) + println(" log10: ", math.Log10(n)) + println(" log2: ", math.Log2(n)) + println(" max: ", math.Max(n, n+1)) + println(" min: ", math.Min(n, n+1)) + println(" mod: ", math.Mod(n, n+1)) + i, f := math.Modf(n) + println(" modf: ", i, f) + println(" pow: ", math.Pow(n, n)) + println(" remainder:", math.Remainder(n, n+0.2)) + println(" sin: ", math.Sin(n)) + println(" sinh: ", math.Sinh(n)) + println(" tan: ", math.Tan(n)) + println(" tanh: ", math.Tanh(n)) + println(" trunc: ", math.Trunc(n)) + } +} diff --git a/testdata/math.txt b/testdata/math.txt new file mode 100644 index 00000000..473ca4fe --- /dev/null +++ b/testdata/math.txt @@ -0,0 +1,216 @@ +n: +3.000000e-001 + asin: +3.046927e-001 + asinh: +2.956730e-001 + acos: +1.266104e+000 + acosh: NaN + atan: +2.914568e-001 + atanh: +3.095196e-001 + atan2: +9.827937e-001 + cbrt: +6.694330e-001 + ceil: +1.000000e+000 + cos: +9.553365e-001 + cosh: +1.045339e+000 + erf: +3.286268e-001 + erfc: +6.713732e-001 + exp: +1.349859e+000 + expm1: +3.498588e-001 + exp2: +1.231144e+000 + floor: +0.000000e+000 + frexp: +6.000000e-001 -1 + hypot: +6.708204e-001 + ldexp: +1.200000e+000 + log: -1.203973e+000 + log1p: +2.623643e-001 + log10: -5.228787e-001 + log2: -1.736966e+000 + max: +1.300000e+000 + min: +3.000000e-001 + mod: +3.000000e-001 + modf: +0.000000e+000 +3.000000e-001 + pow: +6.968453e-001 + remainder: -2.000000e-001 + sin: +2.955202e-001 + sinh: +3.045203e-001 + tan: +3.093362e-001 + tanh: +2.913126e-001 + trunc: +0.000000e+000 +n: +1.500000e+000 + asin: NaN + asinh: +1.194763e+000 + acos: NaN + acosh: +9.624237e-001 + atan: +9.827937e-001 + atanh: NaN + atan2: +1.438245e+000 + cbrt: +1.144714e+000 + ceil: +2.000000e+000 + cos: +7.073720e-002 + cosh: +2.352410e+000 + erf: +9.661051e-001 + erfc: +3.389485e-002 + exp: +4.481689e+000 + expm1: +3.481689e+000 + exp2: +2.828427e+000 + floor: +1.000000e+000 + frexp: +7.500000e-001 1 + hypot: +3.354102e+000 + ldexp: +6.000000e+000 + log: +4.054651e-001 + log1p: +9.162907e-001 + log10: +1.760913e-001 + log2: +5.849625e-001 + max: +2.500000e+000 + min: +1.500000e+000 + mod: +1.500000e+000 + modf: +1.000000e+000 +5.000000e-001 + pow: +1.837117e+000 + remainder: -2.000000e-001 + sin: +9.974950e-001 + sinh: +2.129279e+000 + tan: +1.410142e+001 + tanh: +9.051483e-001 + trunc: +1.000000e+000 +n: +2.600000e+000 + asin: NaN + asinh: +1.683743e+000 + acos: NaN + acosh: +1.609438e+000 + atan: +1.203622e+000 + atanh: NaN + atan2: +1.494024e+000 + cbrt: +1.375069e+000 + ceil: +3.000000e+000 + cos: -8.568888e-001 + cosh: +6.769006e+000 + erf: +9.997640e-001 + erfc: +2.360344e-004 + exp: +1.346374e+001 + expm1: +1.246374e+001 + exp2: +6.062866e+000 + floor: +2.000000e+000 + frexp: +6.500000e-001 2 + hypot: +5.813777e+000 + ldexp: +1.040000e+001 + log: +9.555114e-001 + log1p: +1.280934e+000 + log10: +4.149733e-001 + log2: +1.378512e+000 + max: +3.600000e+000 + min: +2.600000e+000 + mod: +2.600000e+000 + modf: +2.000000e+000 +6.000000e-001 + pow: +1.199308e+001 + remainder: -2.000000e-001 + sin: +5.155014e-001 + sinh: +6.694732e+000 + tan: -6.015966e-001 + tanh: +9.890274e-001 + trunc: +2.000000e+000 +n: -1.100000e+000 + asin: NaN + asinh: -9.503469e-001 + acos: NaN + acosh: NaN + atan: -8.329813e-001 + atanh: NaN + atan2: -1.390943e+000 + cbrt: -1.032280e+000 + ceil: -1.000000e+000 + cos: +4.535961e-001 + cosh: +1.668519e+000 + erf: -8.802051e-001 + erfc: +1.880205e+000 + exp: +3.328711e-001 + expm1: -6.671289e-001 + exp2: +4.665165e-001 + floor: -2.000000e+000 + frexp: -5.500000e-001 1 + hypot: +2.459675e+000 + ldexp: -4.400000e+000 + log: NaN + log1p: NaN + log10: NaN + log2: NaN + max: -1.000000e-001 + min: -1.100000e+000 + mod: -1.000000e-001 + modf: -1.000000e+000 -1.000000e-001 + pow: NaN + remainder: -2.000000e-001 + sin: -8.912074e-001 + sinh: -1.335647e+000 + tan: -1.964760e+000 + tanh: -8.004990e-001 + trunc: -1.000000e+000 +n: -3.100000e+000 + asin: NaN + asinh: -1.849604e+000 + acos: NaN + acosh: NaN + atan: -1.258754e+000 + atanh: NaN + atan2: -1.506369e+000 + cbrt: -1.458100e+000 + ceil: -3.000000e+000 + cos: -9.991352e-001 + cosh: +1.112150e+001 + erf: -9.999884e-001 + erfc: +1.999988e+000 + exp: +4.504920e-002 + expm1: -9.549508e-001 + exp2: +1.166291e-001 + floor: -4.000000e+000 + frexp: -7.750000e-001 2 + hypot: +6.931811e+000 + ldexp: -1.240000e+001 + log: NaN + log1p: NaN + log10: NaN + log2: NaN + max: -2.100000e+000 + min: -3.100000e+000 + mod: -1.000000e+000 + modf: -3.000000e+000 -1.000000e-001 + pow: NaN + remainder: -2.000000e-001 + sin: -4.158066e-002 + sinh: -1.107645e+001 + tan: +4.161665e-002 + tanh: -9.959494e-001 + trunc: -3.000000e+000 +n: -3.800000e+000 + asin: NaN + asinh: -2.045028e+000 + acos: NaN + acosh: NaN + atan: -1.313473e+000 + atanh: NaN + atan2: -1.518213e+000 + cbrt: -1.560491e+000 + ceil: -3.000000e+000 + cos: -7.909677e-001 + cosh: +2.236178e+001 + erf: -9.999999e-001 + erfc: +2.000000e+000 + exp: +2.237077e-002 + expm1: -9.776292e-001 + exp2: +7.179365e-002 + floor: -4.000000e+000 + frexp: -9.500000e-001 2 + hypot: +8.497058e+000 + ldexp: -1.520000e+001 + log: NaN + log1p: NaN + log10: NaN + log2: NaN + max: -2.800000e+000 + min: -3.800000e+000 + mod: -1.000000e+000 + modf: -3.000000e+000 -8.000000e-001 + pow: NaN + remainder: -2.000000e-001 + sin: +6.118579e-001 + sinh: -2.233941e+001 + tan: -7.735561e-001 + tanh: -9.989996e-001 + trunc: -3.000000e+000