From 50e99b571f9250605af153363b14dead0d4a87b7 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 6 Sep 2023 14:03:14 +0200 Subject: [PATCH] Add frame pointer on "enable stacktrace". Set no-trapping-math. Update fmuladd. --- lib/std/io/formatter.c3 | 48 ++++++++++++++++--- lib/std/os/posix/general.c3 | 3 +- lib/std/os/posix/process.c3 | 5 +- src/compiler/llvm_codegen.c | 5 ++ src/compiler/llvm_codegen_expr.c | 26 ++++++---- src/version.h | 2 +- test/test_suite/abi/union_x64.c3t | 2 - test/test_suite/abi/wasm_extern.c3t | 4 +- .../attributes/user_defined_attributes.c3t | 6 +-- test/test_suite/expressions/elvis.c3t | 2 - test/test_suite/expressions/fmuladd.c3t | 28 ++++++++++- test/test_suite/functions/naked_function.c3t | 2 +- test/test_suite/statements/ranged_switch.c3t | 2 +- test/test_suite/statements/while_switch.c3t | 2 +- 14 files changed, 106 insertions(+), 31 deletions(-) diff --git a/lib/std/io/formatter.c3 b/lib/std/io/formatter.c3 index 2c8aba41e..49281c5ea 100644 --- a/lib/std/io/formatter.c3 +++ b/lib/std/io/formatter.c3 @@ -122,13 +122,25 @@ fn usz! Formatter.out_str(&self, any arg) @private case SIGNED_INT: case UNSIGNED_INT: PrintFlags flags = self.flags; - defer self.flags = flags; + uint width = self.width; + defer + { + self.flags = flags; + self.width = width; + } self.flags = {}; + self.width = 0; return self.ntoa_any(arg, 10); case FLOAT: PrintFlags flags = self.flags; - defer self.flags = flags; + uint width = self.width; + defer + { + self.flags = flags; + self.width = width; + } self.flags = {}; + self.width = 0; return self.ftoa(float_from_any(arg)!!); case BOOL: return self.out_substr(*(bool*)arg.ptr ? "true" : "false"); @@ -170,14 +182,26 @@ fn usz! Formatter.out_str(&self, any arg) @private return self.out_str(any { arg.ptr, arg.type.inner }); case POINTER: PrintFlags flags = self.flags; + uint width = self.width; + defer + { + self.flags = flags; + self.width = width; + } self.flags = {}; - defer self.flags = flags; + self.width = 0; return self.ntoa_any(arg, 16); case ARRAY: // this is SomeType[*] so grab the "SomeType" PrintFlags flags = self.flags; - defer self.flags = flags; + uint width = self.width; + defer + { + self.flags = flags; + self.width = width; + } self.flags = {}; + self.width = 0; typeid inner = arg.type.inner; usz size = inner.sizeof; usz alen = arg.type.len; @@ -194,8 +218,14 @@ fn usz! Formatter.out_str(&self, any arg) @private return len; case VECTOR: PrintFlags flags = self.flags; - defer self.flags = flags; + uint width = self.width; + defer + { + self.flags = flags; + self.width = width; + } self.flags = {}; + self.width = 0; // this is SomeType[*] so grab the "SomeType" typeid inner = arg.type.inner; usz size = inner.sizeof; @@ -220,8 +250,14 @@ fn usz! Formatter.out_str(&self, any arg) @private } if (inner == void.typeid) inner = char.typeid; PrintFlags flags = self.flags; - defer self.flags = flags; + uint width = self.width; + defer + { + self.flags = flags; + self.width = width; + } self.flags = {}; + self.width = 0; usz size = inner.sizeof; // Pretend this is a String String* temp = (void*)arg.ptr; diff --git a/lib/std/os/posix/general.c3 b/lib/std/os/posix/general.c3 index 571ac9f94..19f38e399 100644 --- a/lib/std/os/posix/general.c3 +++ b/lib/std/os/posix/general.c3 @@ -1,3 +1,4 @@ module std::os::posix; -extern ZString* environ; \ No newline at end of file +extern ZString* environ; + diff --git a/lib/std/os/posix/process.c3 b/lib/std/os/posix/process.c3 index 4ef659b98..eab619517 100644 --- a/lib/std/os/posix/process.c3 +++ b/lib/std/os/posix/process.c3 @@ -37,7 +37,9 @@ def spawn = posix_spawn; extern fn CInt kill(Pid_t pid, CInt sig); extern fn Pid_t waitpid(Pid_t pid, CInt* stat_loc, int options); extern fn CInt raise(CInt sig); - +extern fn CInt backtrace(void **buffer, CInt size); +extern fn ZString* backtrace_symbols(void** buffer, CInt size); +extern fn void backtrace_symbols_fd(void** buffer, CInt size, CInt fd); macro CInt wEXITSTATUS(CInt status) => (status & 0xff00) >> 8; macro CInt wTERMSIG(CInt status) => status & 0x7f; macro CInt wSTOPSIG(CInt status) => wEXITSTATUS(status); @@ -52,3 +54,4 @@ const CInt __WCOREFLAG = 0x80; const CInt __W_CONTINUED = 0xffff; const CInt WNOHANG = 1; const CInt WUNTRACES = 2; + diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 098fd151a..4c7ac0780 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -980,6 +980,11 @@ void llvm_append_function_attributes(GenContext *c, Decl *decl) ABIArgInfo *ret_abi_info = prototype->ret_abi_info; llvm_emit_param_attributes(c, function, ret_abi_info, true, 0, 0); unsigned params = vec_size(prototype->param_types); + if (c->debug.enable_stacktrace) + { + llvm_attribute_add_string(c, function, "frame-pointer", "all", -1); + } + llvm_attribute_add_string(c, function, "no-trapping-math", "true", -1); if (prototype->ret_by_ref) { ABIArgInfo *info = prototype->ret_by_ref_abi_info; diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 1bd61ef67..29e8901da 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -3947,9 +3947,13 @@ typedef enum { INLINE FmulTransformation llvm_get_fmul_transformation(Expr *lhs, Expr *rhs) { + // x * y + z if (expr_is_mult(lhs)) return FMUL_LHS_MULT; + // -(x * y) + z if (expr_is_neg(lhs) && expr_is_mult(lhs->unary_expr.expr)) return FMUL_LHS_NEG_MULT; + // x + y * z if (expr_is_mult(rhs)) return FMUL_RHS_MULT; + // x - (y * z) if (expr_is_neg(rhs) && expr_is_mult(rhs->unary_expr.expr)) return FMUL_RHS_NEG_MULT; return FMUL_NONE; } @@ -3994,28 +3998,32 @@ INLINE bool llvm_emit_fmuladd_maybe(GenContext *c, BEValue *be_value, Expr *expr break; case FMUL_RHS_MULT: args[2] = llvm_emit_expr_to_rvalue(c, lhs); - if (negate_rhs) - { - args[2] = LLVMBuildFNeg(c->builder, args[2], ""); - negate_result = true; - } args[0] = llvm_emit_exprid_to_rvalue(c, rhs->binary_expr.left); args[1] = llvm_emit_exprid_to_rvalue(c, rhs->binary_expr.right); + if (negate_rhs) + { + args[1] = LLVMBuildFNeg(c->builder, args[1], ""); + negate_result = false; + } break; case FMUL_RHS_NEG_MULT: rhs = rhs->unary_expr.expr; assert(!negate_rhs); + args[0] = llvm_emit_exprid_to_rvalue(c, rhs->binary_expr.left); + args[1] = llvm_emit_exprid_to_rvalue(c, rhs->binary_expr.right); + if (expr_is_neg(lhs)) { + // -x - (y * z) => -(x + y * z) args[2] = llvm_emit_expr_to_rvalue(c, lhs->unary_expr.expr); + negate_result = true; } else { - args[2] = LLVMBuildFNeg(c->builder, llvm_emit_expr_to_rvalue(c, lhs), ""); + // x - (y * z) => x + (-y) * z + args[1] = LLVMBuildFNeg(c->builder, args[1], ""); + args[2] = llvm_emit_expr_to_rvalue(c, lhs->unary_expr.expr); } - args[0] = llvm_emit_exprid_to_rvalue(c, rhs->binary_expr.left); - args[1] = llvm_emit_exprid_to_rvalue(c, rhs->binary_expr.right); - negate_result = true; break; default: UNREACHABLE diff --git a/src/version.h b/src/version.h index 1d1bc9cb4..52ab74850 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.635" \ No newline at end of file +#define COMPILER_VERSION "0.4.636" \ No newline at end of file diff --git a/test/test_suite/abi/union_x64.c3t b/test/test_suite/abi/union_x64.c3t index 614b46be6..c5bf6be56 100644 --- a/test/test_suite/abi/union_x64.c3t +++ b/test/test_suite/abi/union_x64.c3t @@ -33,5 +33,3 @@ entry: call void @hello2(i64 %lo, i64 %hi) ret void } - -attributes #0 = { nounwind } diff --git a/test/test_suite/abi/wasm_extern.c3t b/test/test_suite/abi/wasm_extern.c3t index 51e32740a..fcfb0bd10 100644 --- a/test/test_suite/abi/wasm_extern.c3t +++ b/test/test_suite/abi/wasm_extern.c3t @@ -13,5 +13,5 @@ target triple = "wasm32-unknown-unknown" declare i32 @get_abc() #0 define i32 @fgh() #1 -attributes #0 = { nounwind "wasm-import-name"="get_abc" } -attributes #1 = { nounwind "wasm-export-name"="fgh" } +attributes #0 = { nounwind "no-trapping-math"="true" "wasm-import-name"="get_abc" } +attributes #1 = { nounwind "no-trapping-math"="true" "wasm-export-name"="fgh" } diff --git a/test/test_suite/attributes/user_defined_attributes.c3t b/test/test_suite/attributes/user_defined_attributes.c3t index 98e823261..0ab5e2986 100644 --- a/test/test_suite/attributes/user_defined_attributes.c3t +++ b/test/test_suite/attributes/user_defined_attributes.c3t @@ -53,6 +53,6 @@ entry: call void @test.testme() ret void } -attributes #0 = { noreturn nounwind } -attributes #1 = { noinline nounwind } -attributes #2 = { nounwind } \ No newline at end of file +attributes #0 = { noreturn nounwind "no-trapping-math"="true" } +attributes #1 = { noinline nounwind "no-trapping-math"="true" } +attributes #2 = { nounwind "no-trapping-math"="true" } \ No newline at end of file diff --git a/test/test_suite/expressions/elvis.c3t b/test/test_suite/expressions/elvis.c3t index f739926ab..0f64a0e3d 100644 --- a/test/test_suite/expressions/elvis.c3t +++ b/test/test_suite/expressions/elvis.c3t @@ -65,5 +65,3 @@ cond.phi: ; preds = %cond.rhs, %entry %4 = zext i1 %val to i8 ret i8 %4 } - -attributes #0 = { nounwind } \ No newline at end of file diff --git a/test/test_suite/expressions/fmuladd.c3t b/test/test_suite/expressions/fmuladd.c3t index 959ff8402..2f7f7ef8a 100644 --- a/test/test_suite/expressions/fmuladd.c3t +++ b/test/test_suite/expressions/fmuladd.c3t @@ -49,8 +49,34 @@ fn void main() /* #expect: test.ll %3 = call float @llvm.fmuladd.f32(float %0, float %1, float %2) + %3 = call float @llvm.fmuladd.f32(float %0, float %1, float %2) + + %3 = load float, ptr %c, align 4 + %fneg = fneg float %3 + store float %fneg, ptr %c, align 4 + %4 = load float, ptr %c, align 4 + %5 = fneg float %4 %6 = call float @llvm.fmuladd.f32(float %0, float %1, float %5) + + %fneg = fneg float %3 + store float %fneg, ptr %c, align 4 + %4 = load float, ptr %c, align 4 + %fneg1 = fneg float %4 %5 = call float @llvm.fmuladd.f32(float %0, float %1, float %fneg1) - %6 = call float @llvm.fmuladd.f32(float %0, float %1, float %5) + + %3 = load float, ptr %c, align 4 + %fneg = fneg float %3 + store float %fneg, ptr %c, align 4 + %4 = load float, ptr %c, align 4 + %5 = fneg float %1 + %6 = call float @llvm.fmuladd.f32(float %0, float %5, float %4) + %fneg1 = fneg float %6 + + %3 = load float, ptr %c, align 4 + %fneg = fneg float %3 + store float %fneg, ptr %c, align 4 + %fneg1 = fneg float %0 + %4 = load float, ptr %c, align 4 %5 = call float @llvm.fmuladd.f32(float %fneg1, float %1, float %4) + %fneg2 = fneg float %5 diff --git a/test/test_suite/functions/naked_function.c3t b/test/test_suite/functions/naked_function.c3t index 40c906f5d..385d3bf62 100644 --- a/test/test_suite/functions/naked_function.c3t +++ b/test/test_suite/functions/naked_function.c3t @@ -12,4 +12,4 @@ entry: ret void } -attributes #0 = { naked nounwind } \ No newline at end of file +attributes #0 = { naked nounwind "no-trapping-math"="true" } \ No newline at end of file diff --git a/test/test_suite/statements/ranged_switch.c3t b/test/test_suite/statements/ranged_switch.c3t index 759a0be07..35c06f57c 100644 --- a/test/test_suite/statements/ranged_switch.c3t +++ b/test/test_suite/statements/ranged_switch.c3t @@ -227,4 +227,4 @@ entry: ret i32 0 } -attributes #0 = { nounwind } +attributes #0 = { nounwind "no-trapping-math"="true" } diff --git a/test/test_suite/statements/while_switch.c3t b/test/test_suite/statements/while_switch.c3t index 0167e2c3b..f3c27a9b2 100644 --- a/test/test_suite/statements/while_switch.c3t +++ b/test/test_suite/statements/while_switch.c3t @@ -89,4 +89,4 @@ loop.exit: ; preds = %loop.cond ret i32 0 } -attributes #0 = { nounwind } \ No newline at end of file +attributes #0 = { nounwind "no-trapping-math"="true" } \ No newline at end of file