diff --git a/lib/std/math/math.c3 b/lib/std/math/math.c3 index 4553f03d6..383b8109d 100644 --- a/lib/std/math/math.c3 +++ b/lib/std/math/math.c3 @@ -7,7 +7,6 @@ import std::math::matrix; import std::math::quaternion; attrdef @MathLibc(name) = @extern(name), @link(env::POSIX, "m"); -attrdef @LinkMath = @link(env::POSIX, "m"); const E = 2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466; const LOG2E = 1.44269504088896340735992468100189214; // log2(e) @@ -235,14 +234,14 @@ macro asinh(x) <* @require values::@is_floatlike(x) : `The input must be a floating point value or float vector` *> -macro ceil(x) @LinkMath => $$ceil(x); +macro ceil(x) => $$ceil(x); <* Ceil for compile time evaluation. @require @typeis($input, double) || @typeis($input, float) : "Only float and double may be used" *> -macro @ceil($input) @const @LinkMath => $$ceil($input); +macro @ceil($input) @const => $$ceil($input); <* Constrain the value to lie within the given interval. @@ -256,18 +255,18 @@ macro @ceil($input) @const @LinkMath => $$ceil($input); @require values::@assign_to(lower, x) : `The lower bound must be convertable to the value type.` @require values::@assign_to(upper, x) : `The upper bound must be convertable to the value type.` *> -macro clamp(x, lower, upper) @LinkMath => $$max(($typeof(x))lower, $$min(x, ($typeof(x))upper)); +macro clamp(x, lower, upper) => $$max(($typeof(x))lower, $$min(x, ($typeof(x))upper)); <* @require values::@is_promotable_to_floatlike(mag) : `The input must be a number value or float vector` @require $defined(($typeof(values::promote_int(mag)))mag) : `It's not possible to cast the sign to the type of the magnitude` *> -macro copysign(mag, sgn) @LinkMath => $$copysign(values::promote_int_same(mag, sgn), ($typeof(values::promote_int_same(mag, sgn)))sgn); +macro copysign(mag, sgn) => $$copysign(values::promote_int_same(mag, sgn), ($typeof(values::promote_int_same(mag, sgn)))sgn); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number value or float vector` *> -macro cos(x) @LinkMath => $$cos(values::promote_int(x)); +macro cos(x) => $$cos(values::promote_int(x)); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number value or float vector` @@ -297,17 +296,17 @@ macro cotanh(x) => (exp(2.0 * x) + 1.0) / (exp(2.0 * x) - 1.0); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number value or float vector` *> -macro exp(x) @LinkMath => $$exp(values::promote_int(x)); +macro exp(x) => $$exp(values::promote_int(x)); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number value or float vector` *> -macro exp2(x) @LinkMath => $$exp2(values::promote_int(x)); +macro exp2(x) => $$exp2(values::promote_int(x)); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number value or float vector` *> -macro floor(x) @LinkMath => $$floor(values::promote_int(x)); +macro floor(x) => $$floor(values::promote_int(x)); <* @require values::@is_promotable_to_floatlike(a) : `The input must be a number or float vector` @@ -316,7 +315,7 @@ macro floor(x) @LinkMath => $$floor(values::promote_int(x)); @require values::@is_same_vector_type(a, b) : `The input types must be equal` @require values::@is_same_vector_type(a, c) : `The input types must match` *> -macro fma(a, b, c) @LinkMath => $$fma(a, b, c); +macro fma(a, b, c) => $$fma(a, b, c); <* @@ -329,13 +328,13 @@ macro hypot(x, y) => sqrt(sqr(x) + sqr(y)); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number or a float vector` *> -macro ln(x) @LinkMath => $$log(values::promote_int(x)); +macro ln(x) => $$log(values::promote_int(x)); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number or a float vector` @require values::@is_promotable_to_floatlike(base) : `The base must be a number or a float vector` *> -macro log(x, base) @LinkMath +macro log(x, base) { return $$log(values::promote_int_same(x, base)) / $$log(values::promote_int_same(base, x)); } @@ -343,12 +342,12 @@ macro log(x, base) @LinkMath <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number or a float vector` *> -macro log2(x) @LinkMath => $$log2(values::promote_int(x)); +macro log2(x) => $$log2(values::promote_int(x)); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number or a float vector` *> -macro log10(x) @LinkMath => $$log10(values::promote_int(x)); +macro log10(x) => $$log10(values::promote_int(x)); <* @require types::is_numerical($typeof(x)) : `The input must be a floating point value or float vector` @@ -1095,21 +1094,21 @@ fn float _frexpf(float x, int* e) } } -macro overflow_add_helper(x, y) @local @LinkMath +macro overflow_add_helper(x, y) @local { $typeof(x) res @noinit; if ($$overflow_add(x, y, &res)) return OVERFLOW?; return res; } -macro overflow_sub_helper(x, y) @local @LinkMath +macro overflow_sub_helper(x, y) @local { $typeof(x) res @noinit; if ($$overflow_sub(x, y, &res)) return OVERFLOW?; return res; } -macro overflow_mul_helper(x, y) @local @LinkMath +macro overflow_mul_helper(x, y) @local { $typeof(x) res @noinit; if ($$overflow_mul(x, y, &res)) return OVERFLOW?; @@ -1123,7 +1122,7 @@ macro overflow_mul_helper(x, y) @local @LinkMath @require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based" @require $defined(*out) &&& values::@is_same_type(*out, a) : "out must be a pointer of the same type as a and b" *> -macro bool overflow_add(a, b, out) @LinkMath => $$overflow_add(a, b, out); +macro bool overflow_add(a, b, out) => $$overflow_add(a, b, out); <* @param [&out] out : "Where the result of the subtraction is stored" @@ -1132,7 +1131,7 @@ macro bool overflow_add(a, b, out) @LinkMath => $$overflow_add(a, b, out); @require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based" @require $defined(*out) &&& values::@is_same_type(*out, a) : "out must be a pointer of the same type as a and b" *> -macro bool overflow_sub(a, b, out) @LinkMath => $$overflow_sub(a, b, out); +macro bool overflow_sub(a, b, out) => $$overflow_sub(a, b, out); <* @param [&out] out : "Where the result of the multiplication is stored" @@ -1141,7 +1140,7 @@ macro bool overflow_sub(a, b, out) @LinkMath => $$overflow_sub(a, b, out); @require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based" @require $defined(*out) &&& values::@is_same_type(*out, a) : "out must be a pointer of the same type as a and b" *> -macro bool overflow_mul(a, b, out) @LinkMath => $$overflow_mul(a, b, out); +macro bool overflow_mul(a, b, out) => $$overflow_mul(a, b, out); <* @require types::is_vector($Type) || ($Type.kindof == ARRAY &&& types::is_numerical($typefrom($Type.inner))) diff --git a/src/build/build_options.c b/src/build/build_options.c index 197ba4d95..b03830082 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -1362,7 +1362,7 @@ static void parse_option(BuildOptions *options) break; } - FAIL_WITH_ERR("Cannot process the unknown option \"%s\".", current_arg); + FAIL_WITH_ERR_LONG("Cannot process the unknown option \"%s\".", current_arg); } BuildOptions parse_arguments(int argc, const char *argv[]) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 2bd2a02ef..9cc60c733 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1877,6 +1877,7 @@ typedef struct CopyStruct_ typedef struct { const char **links; + bool link_math; } Linking; typedef struct diff --git a/src/compiler/linker.c b/src/compiler/linker.c index f0ce6f0db..d03cc712a 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -268,6 +268,7 @@ static void linker_setup_macos(const char ***args_ref, Linker linker_type) error_exit("Cannot crosslink MacOS without providing --macossdk."); } linking_add_link(&compiler.linking, "System"); + if (compiler.linking.link_math) linking_add_link(&compiler.linking, "m"); add_plain_arg("-syslibroot"); add_quote_arg(compiler.build.macos.sysroot); if (is_no_pie(compiler.platform.reloc_model)) add_plain_arg("-no_pie"); @@ -406,6 +407,7 @@ static void linker_setup_linux(const char ***args_ref, Linker linker_type, bool add_plain_arg("-nostdlib"); return; } + if (compiler.linking.link_math) linking_add_link(&compiler.linking, "m"); if (compiler.build.debug_info == DEBUG_INFO_FULL) { add_plain_arg("-rdynamic"); @@ -450,6 +452,7 @@ static void linker_setup_linux(const char ***args_ref, Linker linker_type, bool add_concat_file_arg(crt_dir, "crtn.o"); add_concat_quote_arg("-L", crt_dir); add_plain_arg("--dynamic-linker=/lib64/ld-linux-x86-64.so.2"); + if (compiler.linking.link_math) linking_add_link(&compiler.linking, "m"); linking_add_link(&compiler.linking, "pthread"); linking_add_link(&compiler.linking, "c"); add_plain_arg("-L/usr/lib/"); @@ -525,12 +528,15 @@ static void linker_setup_android(const char ***args_ref, Linker linker_type, boo add_plain_arg(scratch_buffer_copy()); add_plain_arg("-ldl"); + if (compiler.linking.link_math) add_plain_arg("-lm"); add_plain_arg("-lc"); } static void linker_setup_freebsd(const char ***args_ref, Linker linker_type, bool is_dylib) { - if (linker_type == LINKER_CC) { + if (linker_type == LINKER_CC) + { + if (compiler.linking.link_math) linking_add_link(&compiler.linking, "m"); linking_add_link(&compiler.linking, "pthread"); linking_add_link(&compiler.linking, "execinfo"); // for backtrace if (compiler.build.debug_info == DEBUG_INFO_FULL) @@ -573,6 +579,7 @@ static void linker_setup_freebsd(const char ***args_ref, Linker linker_type, boo add_concat_quote_arg("-L", crt_dir); add_plain_arg("--dynamic-linker=/libexec/ld-elf.so.1"); linking_add_link(&compiler.linking, "c"); + if (compiler.linking.link_math) linking_add_link(&compiler.linking, "m"); linking_add_link(&compiler.linking, "gcc"); linking_add_link(&compiler.linking, "gcc_s"); diff --git a/src/compiler/llvm_codegen_builtins.c b/src/compiler/llvm_codegen_builtins.c index d61e1562a..0c4f7ed7c 100644 --- a/src/compiler/llvm_codegen_builtins.c +++ b/src/compiler/llvm_codegen_builtins.c @@ -829,6 +829,7 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) llvm_emit_matrix_multiply(c, result_value, expr); return; case BUILTIN_MATRIX_TRANSPOSE: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.matrix_transpose); return; case BUILTIN_SYSCLOCK: @@ -844,30 +845,39 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) llvm_emit_prefetch(c, result_value, expr); return; case BUILTIN_REDUCE_AND: + compiler.linking.link_math = true; llvm_emit_reduce_int_builtin(c, intrinsic_id.vector_reduce_and, result_value, expr); return; case BUILTIN_REDUCE_OR: + compiler.linking.link_math = true; llvm_emit_reduce_int_builtin(c, intrinsic_id.vector_reduce_or, result_value, expr); return; case BUILTIN_REDUCE_MIN: + compiler.linking.link_math = true; llvm_emit_3_variant_builtin(c, result_value, expr, intrinsic_id.vector_reduce_smin, intrinsic_id.vector_reduce_umin, intrinsic_id.vector_reduce_fmin); return; case BUILTIN_REDUCE_MAX: + compiler.linking.link_math = true; llvm_emit_3_variant_builtin(c, result_value, expr, intrinsic_id.vector_reduce_smax, intrinsic_id.vector_reduce_umax, intrinsic_id.vector_reduce_fmax); return; case BUILTIN_REDUCE_XOR: + compiler.linking.link_math = true; llvm_emit_reduce_int_builtin(c, intrinsic_id.vector_reduce_xor, result_value, expr); return; case BUILTIN_REDUCE_ADD: + compiler.linking.link_math = true; llvm_emit_reduce_int_builtin(c, intrinsic_id.vector_reduce_add, result_value, expr); return; case BUILTIN_REDUCE_MUL: + compiler.linking.link_math = true; llvm_emit_reduce_int_builtin(c, intrinsic_id.vector_reduce_mul, result_value, expr); return; case BUILTIN_REDUCE_FADD: + compiler.linking.link_math = true; llvm_emit_reduce_float_builtin(c, intrinsic_id.vector_reduce_fadd, result_value, expr); return; case BUILTIN_REDUCE_FMUL: + compiler.linking.link_math = true; llvm_emit_reduce_float_builtin(c, intrinsic_id.vector_reduce_fmul, result_value, expr); return; case BUILTIN_EXACT_DIV: @@ -876,15 +886,19 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) case BUILTIN_EXACT_SUB: case BUILTIN_EXACT_MOD: case BUILTIN_EXACT_NEG: + compiler.linking.link_math = true; llvm_emit_wrap_builtin(c, result_value, expr, func); return; case BUILTIN_OVERFLOW_ADD: + compiler.linking.link_math = true; llvm_emit_overflow_builtin(c, result_value, expr, intrinsic_id.sadd_overflow, intrinsic_id.uadd_overflow); return; case BUILTIN_OVERFLOW_SUB: + compiler.linking.link_math = true; llvm_emit_overflow_builtin(c, result_value, expr, intrinsic_id.ssub_overflow, intrinsic_id.usub_overflow); return; case BUILTIN_OVERFLOW_MUL: + compiler.linking.link_math = true; llvm_emit_overflow_builtin(c, result_value, expr, intrinsic_id.smul_overflow, intrinsic_id.umul_overflow); return; case BUILTIN_CTTZ: @@ -926,21 +940,27 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) llvm_emit_3_variant_builtin(c, result_value, expr, intrinsic_id.smin, intrinsic_id.umin, intrinsic_id.minnum); return; case BUILTIN_SAT_SHL: + compiler.linking.link_math = true; llvm_emit_3_variant_builtin(c, result_value, expr, intrinsic_id.sshl_sat, intrinsic_id.ushl_sat, 0); return; case BUILTIN_SAT_ADD: + compiler.linking.link_math = true; llvm_emit_3_variant_builtin(c, result_value, expr, intrinsic_id.sadd_sat, intrinsic_id.uadd_sat, 0); return; case BUILTIN_SAT_SUB: + compiler.linking.link_math = true; llvm_emit_3_variant_builtin(c, result_value, expr, intrinsic_id.ssub_sat, intrinsic_id.usub_sat, 0); return; case BUILTIN_SAT_MUL: + compiler.linking.link_math = true; llvm_emit_3_variant_builtin(c, result_value, expr, intrinsic_id.smul_fixed_sat, intrinsic_id.umul_fixed_sat, 0); return; case BUILTIN_ABS: + compiler.linking.link_math = true; llvm_emit_abs_builtin(c, result_value, expr); return; case BUILTIN_POW_INT: + compiler.linking.link_math = true; llvm_emit_pow_int_builtin(c, result_value, expr); return; case BUILTIN_BITREVERSE: @@ -953,24 +973,31 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.ceil); return; case BUILTIN_COS: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.cos); return; case BUILTIN_COPYSIGN: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.copysign); return; case BUILTIN_FLOOR: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.floor); return; case BUILTIN_EXP: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.exp); return; case BUILTIN_EXP2: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.exp2); return; case BUILTIN_FMA: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.fma); return; case BUILTIN_FMULADD: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.fmuladd); return; case BUILTIN_FSHL: @@ -980,37 +1007,47 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.fshr); return; case BUILTIN_GET_ROUNDING_MODE: + compiler.linking.link_math = true; llvm_value_set(result_value, llvm_emit_call_intrinsic(c, intrinsic_id.get_rounding, NULL, 0, NULL, 0), expr->type); return; case BUILTIN_LOG: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.log); return; case BUILTIN_LOG2: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.log2); return; case BUILTIN_LOG10: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.log10); return; case BUILTIN_POW: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.pow); return; case BUILTIN_NEARBYINT: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.nearbyint); return; case BUILTIN_POPCOUNT: llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.ctpop); return; case BUILTIN_RINT: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.rint); return; case BUILTIN_ROUND: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.round); return; case BUILTIN_ROUNDEVEN: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.roundeven); return; case BUILTIN_SET_ROUNDING_MODE: { + compiler.linking.link_math = true; Expr **args = expr->call_expr.arguments; LLVMValueRef arg_slots[1]; llvm_emit_intrinsic_args(c, args, arg_slots, 1); @@ -1036,23 +1073,30 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) llvm_emit_builtin_args_types3(c, result_value, expr, intrinsic_id.wasm_memory_size, expr->type, NULL, NULL); return; case BUILTIN_SIN: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.sin); return; case BUILTIN_SQRT: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.sqrt); return; case BUILTIN_TRUNC: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.trunc); return; case BUILTIN_LRINT: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.lrint); return; case BUILTIN_LROUND: + compiler.linking.link_math = true; llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.lround); return; case BUILTIN_LLRINT: + compiler.linking.link_math = true; TODO case BUILTIN_LLROUND: + compiler.linking.link_math = true; TODO case BUILTIN_STR_HASH: case BUILTIN_STR_LOWER: