| author | |
| committer | |
| log | e7f128c2051b086cdb1c03da041745b560bbaa3e |
| tree | 89d06ee67639dfa0260c5beabc344fb33099df0d |
| parent | c9d990d79083f117564837f762c3e225d7fbc5cf |
| parent | 4eb3f50fcf6fcfb6b8013571be00b9eeeb909833 |
| signature |
add `@trap` builtin28 files changed, 203 insertions(+), 34 deletions(-)
doc/langref.html.in+16-1| ... | @@ -7818,12 +7818,14 @@ comptime { | ... | @@ -7818,12 +7818,14 @@ comptime { |
| 7818 | <p> | 7818 | <p> |
| 7819 | This function inserts a platform-specific debug trap instruction which causes | 7819 | This function inserts a platform-specific debug trap instruction which causes |
| 7820 | debuggers to break there. | 7820 | debuggers to break there. |
| 7821 | Unlike for {#syntax#}@trap(){#endsyntax#}, execution may continue after this point if the program is resumed. | ||
| 7821 | </p> | 7822 | </p> |
| 7822 | <p> | 7823 | <p> |
| 7823 | This function is only valid within function scope. | 7824 | This function is only valid within function scope. |
| 7824 | </p> | 7825 | </p> |
| 7825 | 7826 | {#see_also|@trap#} | |
| 7826 | {#header_close#} | 7827 | {#header_close#} |
| 7828 | |||
| 7827 | {#header_open|@mulAdd#} | 7829 | {#header_open|@mulAdd#} |
| 7828 | <pre>{#syntax#}@mulAdd(comptime T: type, a: T, b: T, c: T) T{#endsyntax#}</pre> | 7830 | <pre>{#syntax#}@mulAdd(comptime T: type, a: T, b: T, c: T) T{#endsyntax#}</pre> |
| 7829 | <p> | 7831 | <p> |
| ... | @@ -9393,6 +9395,19 @@ fn List(comptime T: type) type { | ... | @@ -9393,6 +9395,19 @@ fn List(comptime T: type) type { |
| 9393 | </p> | 9395 | </p> |
| 9394 | {#header_close#} | 9396 | {#header_close#} |
| 9395 | 9397 | ||
| 9398 | {#header_open|@trap#} | ||
| 9399 | <pre>{#syntax#}@trap() noreturn{#endsyntax#}</pre> | ||
| 9400 | <p> | ||
| 9401 | This function inserts a platform-specific trap/jam instruction which can be used to exit the program abnormally. | ||
| 9402 | This may be implemented by explicitly emitting an invalid instruction which may cause an illegal instruction exception of some sort. | ||
| 9403 | Unlike for {#syntax#}@breakpoint(){#endsyntax#}, execution does not continue after this point. | ||
| 9404 | </p> | ||
| 9405 | <p> | ||
| 9406 | This function is only valid within function scope. | ||
| 9407 | </p> | ||
| 9408 | {#see_also|@breakpoint#} | ||
| 9409 | {#header_close#} | ||
| 9410 | |||
| 9396 | {#header_open|@truncate#} | 9411 | {#header_open|@truncate#} |
| 9397 | <pre>{#syntax#}@truncate(comptime T: type, integer: anytype) T{#endsyntax#}</pre> | 9412 | <pre>{#syntax#}@truncate(comptime T: type, integer: anytype) T{#endsyntax#}</pre> |
| 9398 | <p> | 9413 | <p> |
lib/docs/main.js-4| ... | @@ -1187,10 +1187,6 @@ const NAV_MODES = { | ... | @@ -1187,10 +1187,6 @@ const NAV_MODES = { |
| 1187 | payloadHtml += "panic"; | 1187 | payloadHtml += "panic"; |
| 1188 | break; | 1188 | break; |
| 1189 | } | 1189 | } |
| 1190 | case "set_cold": { | ||
| 1191 | payloadHtml += "setCold"; | ||
| 1192 | break; | ||
| 1193 | } | ||
| 1194 | case "set_runtime_safety": { | 1190 | case "set_runtime_safety": { |
| 1195 | payloadHtml += "setRuntimeSafety"; | 1191 | payloadHtml += "setRuntimeSafety"; |
| 1196 | break; | 1192 | break; |
lib/zig.h+8-2| ... | @@ -180,10 +180,16 @@ typedef char bool; | ... | @@ -180,10 +180,16 @@ typedef char bool; |
| 180 | #define zig_export(sig, symbol, name) __asm(name " = " symbol) | 180 | #define zig_export(sig, symbol, name) __asm(name " = " symbol) |
| 181 | #endif | 181 | #endif |
| 182 | 182 | ||
| 183 | #if zig_has_builtin(trap) | ||
| 184 | #define zig_trap() __builtin_trap() | ||
| 185 | #elif defined(__i386__) || defined(__x86_64__) | ||
| 186 | #define zig_trap() __asm__ volatile("ud2"); | ||
| 187 | #else | ||
| 188 | #define zig_trap() raise(SIGILL) | ||
| 189 | #endif | ||
| 190 | |||
| 183 | #if zig_has_builtin(debugtrap) | 191 | #if zig_has_builtin(debugtrap) |
| 184 | #define zig_breakpoint() __builtin_debugtrap() | 192 | #define zig_breakpoint() __builtin_debugtrap() |
| 185 | #elif zig_has_builtin(trap) || defined(zig_gnuc) | ||
| 186 | #define zig_breakpoint() __builtin_trap() | ||
| 187 | #elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) | 193 | #elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) |
| 188 | #define zig_breakpoint() __debugbreak() | 194 | #define zig_breakpoint() __debugbreak() |
| 189 | #elif defined(__i386__) || defined(__x86_64__) | 195 | #elif defined(__i386__) || defined(__x86_64__) |
src/Air.zig+9-1| ... | @@ -232,7 +232,14 @@ pub const Inst = struct { | ... | @@ -232,7 +232,14 @@ pub const Inst = struct { |
| 232 | /// Result type is always noreturn; no instructions in a block follow this one. | 232 | /// Result type is always noreturn; no instructions in a block follow this one. |
| 233 | /// Uses the `br` field. | 233 | /// Uses the `br` field. |
| 234 | br, | 234 | br, |
| 235 | /// Lowers to a hardware trap instruction, or the next best thing. | 235 | /// Lowers to a trap/jam instruction causing program abortion. |
| 236 | /// This may lower to an instruction known to be invalid. | ||
| 237 | /// Sometimes, for the lack of a better instruction, `trap` and `breakpoint` may compile down to the same code. | ||
| 238 | /// Result type is always noreturn; no instructions in a block follow this one. | ||
| 239 | trap, | ||
| 240 | /// Lowers to a trap instruction causing debuggers to break here, or the next best thing. | ||
| 241 | /// The debugger or something else may allow the program to resume after this point. | ||
| 242 | /// Sometimes, for the lack of a better instruction, `trap` and `breakpoint` may compile down to the same code. | ||
| 236 | /// Result type is always void. | 243 | /// Result type is always void. |
| 237 | breakpoint, | 244 | breakpoint, |
| 238 | /// Yields the return address of the current function. | 245 | /// Yields the return address of the current function. |
| ... | @@ -1186,6 +1193,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -1186,6 +1193,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 1186 | .ret, | 1193 | .ret, |
| 1187 | .ret_load, | 1194 | .ret_load, |
| 1188 | .unreach, | 1195 | .unreach, |
| 1196 | .trap, | ||
| 1189 | => return Type.initTag(.noreturn), | 1197 | => return Type.initTag(.noreturn), |
| 1190 | 1198 | ||
| 1191 | .breakpoint, | 1199 | .breakpoint, |
src/AstGen.zig+17-4| ... | @@ -2609,8 +2609,9 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2609,8 +2609,9 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2609 | .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) { | 2609 | .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) { |
| 2610 | .breakpoint, | 2610 | .breakpoint, |
| 2611 | .fence, | 2611 | .fence, |
| 2612 | .set_align_stack, | ||
| 2613 | .set_float_mode, | 2612 | .set_float_mode, |
| 2613 | .set_align_stack, | ||
| 2614 | .set_cold, | ||
| 2614 | => break :b true, | 2615 | => break :b true, |
| 2615 | else => break :b false, | 2616 | else => break :b false, |
| 2616 | }, | 2617 | }, |
| ... | @@ -2630,6 +2631,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2630,6 +2631,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2630 | .repeat_inline, | 2631 | .repeat_inline, |
| 2631 | .panic, | 2632 | .panic, |
| 2632 | .panic_comptime, | 2633 | .panic_comptime, |
| 2634 | .trap, | ||
| 2633 | .check_comptime_control_flow, | 2635 | .check_comptime_control_flow, |
| 2634 | => { | 2636 | => { |
| 2635 | noreturn_src_node = statement; | 2637 | noreturn_src_node = statement; |
| ... | @@ -2658,7 +2660,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2658,7 +2660,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2658 | .validate_struct_init_comptime, | 2660 | .validate_struct_init_comptime, |
| 2659 | .validate_array_init, | 2661 | .validate_array_init, |
| 2660 | .validate_array_init_comptime, | 2662 | .validate_array_init_comptime, |
| 2661 | .set_cold, | ||
| 2662 | .set_runtime_safety, | 2663 | .set_runtime_safety, |
| 2663 | .closure_capture, | 2664 | .closure_capture, |
| 2664 | .memcpy, | 2665 | .memcpy, |
| ... | @@ -8081,6 +8082,14 @@ fn builtinCall( | ... | @@ -8081,6 +8082,14 @@ fn builtinCall( |
| 8081 | }); | 8082 | }); |
| 8082 | return rvalue(gz, ri, result, node); | 8083 | return rvalue(gz, ri, result, node); |
| 8083 | }, | 8084 | }, |
| 8085 | .set_cold => { | ||
| 8086 | const order = try expr(gz, scope, ri, params[0]); | ||
| 8087 | const result = try gz.addExtendedPayload(.set_cold, Zir.Inst.UnNode{ | ||
| 8088 | .node = gz.nodeIndexToRelative(node), | ||
| 8089 | .operand = order, | ||
| 8090 | }); | ||
| 8091 | return rvalue(gz, ri, result, node); | ||
| 8092 | }, | ||
| 8084 | 8093 | ||
| 8085 | .src => { | 8094 | .src => { |
| 8086 | const token_starts = tree.tokens.items(.start); | 8095 | const token_starts = tree.tokens.items(.start); |
| ... | @@ -8100,7 +8109,7 @@ fn builtinCall( | ... | @@ -8100,7 +8109,7 @@ fn builtinCall( |
| 8100 | .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node), | 8109 | .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node), |
| 8101 | .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node), | 8110 | .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node), |
| 8102 | .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node), | 8111 | .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node), |
| 8103 | .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node), | 8112 | .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node), |
| 8104 | 8113 | ||
| 8105 | .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info), | 8114 | .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info), |
| 8106 | .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of), | 8115 | .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of), |
| ... | @@ -8114,7 +8123,6 @@ fn builtinCall( | ... | @@ -8114,7 +8123,6 @@ fn builtinCall( |
| 8114 | .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int), | 8123 | .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int), |
| 8115 | .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .embed_file), | 8124 | .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .embed_file), |
| 8116 | .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name), | 8125 | .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name), |
| 8117 | .set_cold => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_cold), | ||
| 8118 | .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety), | 8126 | .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety), |
| 8119 | .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt), | 8127 | .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt), |
| 8120 | .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin), | 8128 | .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin), |
| ... | @@ -8174,6 +8182,11 @@ fn builtinCall( | ... | @@ -8174,6 +8182,11 @@ fn builtinCall( |
| 8174 | try emitDbgNode(gz, node); | 8182 | try emitDbgNode(gz, node); |
| 8175 | return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], if (gz.force_comptime) .panic_comptime else .panic); | 8183 | return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], if (gz.force_comptime) .panic_comptime else .panic); |
| 8176 | }, | 8184 | }, |
| 8185 | .trap => { | ||
| 8186 | try emitDbgNode(gz, node); | ||
| 8187 | _ = try gz.addNode(.trap, node); | ||
| 8188 | return rvalue(gz, ri, .void_value, node); | ||
| 8189 | }, | ||
| 8177 | .error_to_int => { | 8190 | .error_to_int => { |
| 8178 | const operand = try expr(gz, scope, .{ .rl = .none }, params[0]); | 8191 | const operand = try expr(gz, scope, .{ .rl = .none }, params[0]); |
| 8179 | const result = try gz.addExtendedPayload(.error_to_int, Zir.Inst.UnNode{ | 8192 | const result = try gz.addExtendedPayload(.error_to_int, Zir.Inst.UnNode{ |
src/Autodoc.zig-1| ... | @@ -1338,7 +1338,6 @@ fn walkInstruction( | ... | @@ -1338,7 +1338,6 @@ fn walkInstruction( |
| 1338 | .embed_file, | 1338 | .embed_file, |
| 1339 | .error_name, | 1339 | .error_name, |
| 1340 | .panic, | 1340 | .panic, |
| 1341 | .set_cold, // @check | ||
| 1342 | .set_runtime_safety, // @check | 1341 | .set_runtime_safety, // @check |
| 1343 | .sqrt, | 1342 | .sqrt, |
| 1344 | .sin, | 1343 | .sin, |
src/BuiltinFn.zig+8| ... | @@ -109,6 +109,7 @@ pub const Tag = enum { | ... | @@ -109,6 +109,7 @@ pub const Tag = enum { |
| 109 | sub_with_overflow, | 109 | sub_with_overflow, |
| 110 | tag_name, | 110 | tag_name, |
| 111 | This, | 111 | This, |
| 112 | trap, | ||
| 112 | truncate, | 113 | truncate, |
| 113 | Type, | 114 | Type, |
| 114 | type_info, | 115 | type_info, |
| ... | @@ -915,6 +916,13 @@ pub const list = list: { | ... | @@ -915,6 +916,13 @@ pub const list = list: { |
| 915 | .param_count = 0, | 916 | .param_count = 0, |
| 916 | }, | 917 | }, |
| 917 | }, | 918 | }, |
| 919 | .{ | ||
| 920 | "@trap", | ||
| 921 | .{ | ||
| 922 | .tag = .trap, | ||
| 923 | .param_count = 0, | ||
| 924 | }, | ||
| 925 | }, | ||
| 918 | .{ | 926 | .{ |
| 919 | "@truncate", | 927 | "@truncate", |
| 920 | .{ | 928 | .{ |
src/Liveness.zig+2| ... | @@ -226,6 +226,7 @@ pub fn categorizeOperand( | ... | @@ -226,6 +226,7 @@ pub fn categorizeOperand( |
| 226 | .ret_ptr, | 226 | .ret_ptr, |
| 227 | .constant, | 227 | .constant, |
| 228 | .const_ty, | 228 | .const_ty, |
| 229 | .trap, | ||
| 229 | .breakpoint, | 230 | .breakpoint, |
| 230 | .dbg_stmt, | 231 | .dbg_stmt, |
| 231 | .dbg_inline_begin, | 232 | .dbg_inline_begin, |
| ... | @@ -848,6 +849,7 @@ fn analyzeInst( | ... | @@ -848,6 +849,7 @@ fn analyzeInst( |
| 848 | .ret_ptr, | 849 | .ret_ptr, |
| 849 | .constant, | 850 | .constant, |
| 850 | .const_ty, | 851 | .const_ty, |
| 852 | .trap, | ||
| 851 | .breakpoint, | 853 | .breakpoint, |
| 852 | .dbg_stmt, | 854 | .dbg_stmt, |
| 853 | .dbg_inline_begin, | 855 | .dbg_inline_begin, |
src/Sema.zig+18-9| ... | @@ -1101,6 +1101,7 @@ fn analyzeBodyInner( | ... | @@ -1101,6 +1101,7 @@ fn analyzeBodyInner( |
| 1101 | .@"unreachable" => break sema.zirUnreachable(block, inst), | 1101 | .@"unreachable" => break sema.zirUnreachable(block, inst), |
| 1102 | .panic => break sema.zirPanic(block, inst, false), | 1102 | .panic => break sema.zirPanic(block, inst, false), |
| 1103 | .panic_comptime => break sema.zirPanic(block, inst, true), | 1103 | .panic_comptime => break sema.zirPanic(block, inst, true), |
| 1104 | .trap => break sema.zirTrap(block, inst), | ||
| 1104 | // zig fmt: on | 1105 | // zig fmt: on |
| 1105 | 1106 | ||
| 1106 | .extended => ext: { | 1107 | .extended => ext: { |
| ... | @@ -1167,6 +1168,11 @@ fn analyzeBodyInner( | ... | @@ -1167,6 +1168,11 @@ fn analyzeBodyInner( |
| 1167 | i += 1; | 1168 | i += 1; |
| 1168 | continue; | 1169 | continue; |
| 1169 | }, | 1170 | }, |
| 1171 | .set_cold => { | ||
| 1172 | try sema.zirSetCold(block, extended); | ||
| 1173 | i += 1; | ||
| 1174 | continue; | ||
| 1175 | }, | ||
| 1170 | .breakpoint => { | 1176 | .breakpoint => { |
| 1171 | if (!block.is_comptime) { | 1177 | if (!block.is_comptime) { |
| 1172 | _ = try block.addNoOp(.breakpoint); | 1178 | _ = try block.addNoOp(.breakpoint); |
| ... | @@ -1304,11 +1310,6 @@ fn analyzeBodyInner( | ... | @@ -1304,11 +1310,6 @@ fn analyzeBodyInner( |
| 1304 | i += 1; | 1310 | i += 1; |
| 1305 | continue; | 1311 | continue; |
| 1306 | }, | 1312 | }, |
| 1307 | .set_cold => { | ||
| 1308 | try sema.zirSetCold(block, inst); | ||
| 1309 | i += 1; | ||
| 1310 | continue; | ||
| 1311 | }, | ||
| 1312 | .set_runtime_safety => { | 1313 | .set_runtime_safety => { |
| 1313 | try sema.zirSetRuntimeSafety(block, inst); | 1314 | try sema.zirSetRuntimeSafety(block, inst); |
| 1314 | i += 1; | 1315 | i += 1; |
| ... | @@ -5144,6 +5145,14 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index, force_comptime: bo | ... | @@ -5144,6 +5145,14 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index, force_comptime: bo |
| 5144 | return always_noreturn; | 5145 | return always_noreturn; |
| 5145 | } | 5146 | } |
| 5146 | 5147 | ||
| 5148 | fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { | ||
| 5149 | const src_node = sema.code.instructions.items(.data)[inst].node; | ||
| 5150 | const src = LazySrcLoc.nodeOffset(src_node); | ||
| 5151 | sema.src = src; | ||
| 5152 | _ = try block.addNoOp(.trap); | ||
| 5153 | return always_noreturn; | ||
| 5154 | } | ||
| 5155 | |||
| 5147 | fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 5156 | fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 5148 | const tracy = trace(@src()); | 5157 | const tracy = trace(@src()); |
| 5149 | defer tracy.end(); | 5158 | defer tracy.end(); |
| ... | @@ -5721,10 +5730,10 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst | ... | @@ -5721,10 +5730,10 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 5721 | gop.value_ptr.* = .{ .alignment = alignment, .src = src }; | 5730 | gop.value_ptr.* = .{ .alignment = alignment, .src = src }; |
| 5722 | } | 5731 | } |
| 5723 | 5732 | ||
| 5724 | fn zirSetCold(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 5733 | fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| 5725 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 5734 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 5726 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 5735 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 5727 | const is_cold = try sema.resolveConstBool(block, operand_src, inst_data.operand, "operand to @setCold must be comptime-known"); | 5736 | const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, "operand to @setCold must be comptime-known"); |
| 5728 | const func = sema.func orelse return; // does nothing outside a function | 5737 | const func = sema.func orelse return; // does nothing outside a function |
| 5729 | func.is_cold = is_cold; | 5738 | func.is_cold = is_cold; |
| 5730 | } | 5739 | } |
src/Zir.zig+13-8| ... | @@ -617,7 +617,7 @@ pub const Inst = struct { | ... | @@ -617,7 +617,7 @@ pub const Inst = struct { |
| 617 | /// Uses the `un_node` field. | 617 | /// Uses the `un_node` field. |
| 618 | typeof_log2_int_type, | 618 | typeof_log2_int_type, |
| 619 | /// Asserts control-flow will not reach this instruction (`unreachable`). | 619 | /// Asserts control-flow will not reach this instruction (`unreachable`). |
| 620 | /// Uses the `unreachable` union field. | 620 | /// Uses the `@"unreachable"` union field. |
| 621 | @"unreachable", | 621 | @"unreachable", |
| 622 | /// Bitwise XOR. `^` | 622 | /// Bitwise XOR. `^` |
| 623 | /// Uses the `pl_node` union field. Payload is `Bin`. | 623 | /// Uses the `pl_node` union field. Payload is `Bin`. |
| ... | @@ -808,8 +808,9 @@ pub const Inst = struct { | ... | @@ -808,8 +808,9 @@ pub const Inst = struct { |
| 808 | panic, | 808 | panic, |
| 809 | /// Same as `panic` but forces comptime. | 809 | /// Same as `panic` but forces comptime. |
| 810 | panic_comptime, | 810 | panic_comptime, |
| 811 | /// Implement builtin `@setCold`. Uses `un_node`. | 811 | /// Implements `@trap`. |
| 812 | set_cold, | 812 | /// Uses the `node` field. |
| 813 | trap, | ||
| 813 | /// Implement builtin `@setRuntimeSafety`. Uses `un_node`. | 814 | /// Implement builtin `@setRuntimeSafety`. Uses `un_node`. |
| 814 | set_runtime_safety, | 815 | set_runtime_safety, |
| 815 | /// Implement builtin `@sqrt`. Uses `un_node`. | 816 | /// Implement builtin `@sqrt`. Uses `un_node`. |
| ... | @@ -1187,7 +1188,6 @@ pub const Inst = struct { | ... | @@ -1187,7 +1188,6 @@ pub const Inst = struct { |
| 1187 | .bool_to_int, | 1188 | .bool_to_int, |
| 1188 | .embed_file, | 1189 | .embed_file, |
| 1189 | .error_name, | 1190 | .error_name, |
| 1190 | .set_cold, | ||
| 1191 | .set_runtime_safety, | 1191 | .set_runtime_safety, |
| 1192 | .sqrt, | 1192 | .sqrt, |
| 1193 | .sin, | 1193 | .sin, |
| ... | @@ -1277,6 +1277,7 @@ pub const Inst = struct { | ... | @@ -1277,6 +1277,7 @@ pub const Inst = struct { |
| 1277 | .repeat_inline, | 1277 | .repeat_inline, |
| 1278 | .panic, | 1278 | .panic, |
| 1279 | .panic_comptime, | 1279 | .panic_comptime, |
| 1280 | .trap, | ||
| 1280 | .check_comptime_control_flow, | 1281 | .check_comptime_control_flow, |
| 1281 | => true, | 1282 | => true, |
| 1282 | }; | 1283 | }; |
| ... | @@ -1323,7 +1324,6 @@ pub const Inst = struct { | ... | @@ -1323,7 +1324,6 @@ pub const Inst = struct { |
| 1323 | .validate_deref, | 1324 | .validate_deref, |
| 1324 | .@"export", | 1325 | .@"export", |
| 1325 | .export_value, | 1326 | .export_value, |
| 1326 | .set_cold, | ||
| 1327 | .set_runtime_safety, | 1327 | .set_runtime_safety, |
| 1328 | .memcpy, | 1328 | .memcpy, |
| 1329 | .memset, | 1329 | .memset, |
| ... | @@ -1553,6 +1553,7 @@ pub const Inst = struct { | ... | @@ -1553,6 +1553,7 @@ pub const Inst = struct { |
| 1553 | .repeat_inline, | 1553 | .repeat_inline, |
| 1554 | .panic, | 1554 | .panic, |
| 1555 | .panic_comptime, | 1555 | .panic_comptime, |
| 1556 | .trap, | ||
| 1556 | .for_len, | 1557 | .for_len, |
| 1557 | .@"try", | 1558 | .@"try", |
| 1558 | .try_ptr, | 1559 | .try_ptr, |
| ... | @@ -1561,7 +1562,7 @@ pub const Inst = struct { | ... | @@ -1561,7 +1562,7 @@ pub const Inst = struct { |
| 1561 | => false, | 1562 | => false, |
| 1562 | 1563 | ||
| 1563 | .extended => switch (data.extended.opcode) { | 1564 | .extended => switch (data.extended.opcode) { |
| 1564 | .breakpoint, .fence => true, | 1565 | .fence, .set_cold, .breakpoint => true, |
| 1565 | else => false, | 1566 | else => false, |
| 1566 | }, | 1567 | }, |
| 1567 | }; | 1568 | }; |
| ... | @@ -1750,7 +1751,7 @@ pub const Inst = struct { | ... | @@ -1750,7 +1751,7 @@ pub const Inst = struct { |
| 1750 | .error_name = .un_node, | 1751 | .error_name = .un_node, |
| 1751 | .panic = .un_node, | 1752 | .panic = .un_node, |
| 1752 | .panic_comptime = .un_node, | 1753 | .panic_comptime = .un_node, |
| 1753 | .set_cold = .un_node, | 1754 | .trap = .node, |
| 1754 | .set_runtime_safety = .un_node, | 1755 | .set_runtime_safety = .un_node, |
| 1755 | .sqrt = .un_node, | 1756 | .sqrt = .un_node, |
| 1756 | .sin = .un_node, | 1757 | .sin = .un_node, |
| ... | @@ -1979,11 +1980,15 @@ pub const Inst = struct { | ... | @@ -1979,11 +1980,15 @@ pub const Inst = struct { |
| 1979 | /// Implement builtin `@setAlignStack`. | 1980 | /// Implement builtin `@setAlignStack`. |
| 1980 | /// `operand` is payload index to `UnNode`. | 1981 | /// `operand` is payload index to `UnNode`. |
| 1981 | set_align_stack, | 1982 | set_align_stack, |
| 1983 | /// Implements `@setCold`. | ||
| 1984 | /// `operand` is payload index to `UnNode`. | ||
| 1985 | set_cold, | ||
| 1982 | /// Implements the `@errSetCast` builtin. | 1986 | /// Implements the `@errSetCast` builtin. |
| 1983 | /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. | 1987 | /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. |
| 1984 | err_set_cast, | 1988 | err_set_cast, |
| 1985 | /// `operand` is payload index to `UnNode`. | 1989 | /// `operand` is payload index to `UnNode`. |
| 1986 | await_nosuspend, | 1990 | await_nosuspend, |
| 1991 | /// Implements `@breakpoint`. | ||
| 1987 | /// `operand` is `src_node: i32`. | 1992 | /// `operand` is `src_node: i32`. |
| 1988 | breakpoint, | 1993 | breakpoint, |
| 1989 | /// Implements the `@select` builtin. | 1994 | /// Implements the `@select` builtin. |
| ... | @@ -1997,7 +2002,7 @@ pub const Inst = struct { | ... | @@ -1997,7 +2002,7 @@ pub const Inst = struct { |
| 1997 | int_to_error, | 2002 | int_to_error, |
| 1998 | /// Implement builtin `@Type`. | 2003 | /// Implement builtin `@Type`. |
| 1999 | /// `operand` is payload index to `UnNode`. | 2004 | /// `operand` is payload index to `UnNode`. |
| 2000 | /// `small` contains `NameStrategy | 2005 | /// `small` contains `NameStrategy`. |
| 2001 | reify, | 2006 | reify, |
| 2002 | /// Implements the `@asyncCall` builtin. | 2007 | /// Implements the `@asyncCall` builtin. |
| 2003 | /// `operand` is payload index to `AsyncCall`. | 2008 | /// `operand` is payload index to `AsyncCall`. |
src/arch/aarch64/CodeGen.zig+10-1| ... | @@ -733,6 +733,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -733,6 +733,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 733 | .bitcast => try self.airBitCast(inst), | 733 | .bitcast => try self.airBitCast(inst), |
| 734 | .block => try self.airBlock(inst), | 734 | .block => try self.airBlock(inst), |
| 735 | .br => try self.airBr(inst), | 735 | .br => try self.airBr(inst), |
| 736 | .trap => try self.airTrap(), | ||
| 736 | .breakpoint => try self.airBreakpoint(), | 737 | .breakpoint => try self.airBreakpoint(), |
| 737 | .ret_addr => try self.airRetAddr(inst), | 738 | .ret_addr => try self.airRetAddr(inst), |
| 738 | .frame_addr => try self.airFrameAddress(inst), | 739 | .frame_addr => try self.airFrameAddress(inst), |
| ... | @@ -4194,10 +4195,18 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4194,10 +4195,18 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 4194 | return self.finishAir(inst, result, .{ .none, .none, .none }); | 4195 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 4195 | } | 4196 | } |
| 4196 | 4197 | ||
| 4198 | fn airTrap(self: *Self) !void { | ||
| 4199 | _ = try self.addInst(.{ | ||
| 4200 | .tag = .brk, | ||
| 4201 | .data = .{ .imm16 = 0x0001 }, | ||
| 4202 | }); | ||
| 4203 | return self.finishAirBookkeeping(); | ||
| 4204 | } | ||
| 4205 | |||
| 4197 | fn airBreakpoint(self: *Self) !void { | 4206 | fn airBreakpoint(self: *Self) !void { |
| 4198 | _ = try self.addInst(.{ | 4207 | _ = try self.addInst(.{ |
| 4199 | .tag = .brk, | 4208 | .tag = .brk, |
| 4200 | .data = .{ .imm16 = 1 }, | 4209 | .data = .{ .imm16 = 0xf000 }, |
| 4201 | }); | 4210 | }); |
| 4202 | return self.finishAirBookkeeping(); | 4211 | return self.finishAirBookkeeping(); |
| 4203 | } | 4212 | } |
src/arch/arm/CodeGen.zig+9| ... | @@ -717,6 +717,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -717,6 +717,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 717 | .bitcast => try self.airBitCast(inst), | 717 | .bitcast => try self.airBitCast(inst), |
| 718 | .block => try self.airBlock(inst), | 718 | .block => try self.airBlock(inst), |
| 719 | .br => try self.airBr(inst), | 719 | .br => try self.airBr(inst), |
| 720 | .trap => try self.airTrap(), | ||
| 720 | .breakpoint => try self.airBreakpoint(), | 721 | .breakpoint => try self.airBreakpoint(), |
| 721 | .ret_addr => try self.airRetAddr(inst), | 722 | .ret_addr => try self.airRetAddr(inst), |
| 722 | .frame_addr => try self.airFrameAddress(inst), | 723 | .frame_addr => try self.airFrameAddress(inst), |
| ... | @@ -4142,6 +4143,14 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4142,6 +4143,14 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 4142 | return self.finishAir(inst, result, .{ .none, .none, .none }); | 4143 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 4143 | } | 4144 | } |
| 4144 | 4145 | ||
| 4146 | fn airTrap(self: *Self) !void { | ||
| 4147 | _ = try self.addInst(.{ | ||
| 4148 | .tag = .undefined_instruction, | ||
| 4149 | .data = .{ .nop = {} }, | ||
| 4150 | }); | ||
| 4151 | return self.finishAirBookkeeping(); | ||
| 4152 | } | ||
| 4153 | |||
| 4145 | fn airBreakpoint(self: *Self) !void { | 4154 | fn airBreakpoint(self: *Self) !void { |
| 4146 | _ = try self.addInst(.{ | 4155 | _ = try self.addInst(.{ |
| 4147 | .tag = .bkpt, | 4156 | .tag = .bkpt, |
src/arch/arm/Emit.zig+7-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | //! This file contains the functionality for lowering AArch64 MIR into | 1 | //! This file contains the functionality for lowering AArch32 MIR into |
| 2 | //! machine code | 2 | //! machine code |
| 3 | 3 | ||
| 4 | const Emit = @This(); | 4 | const Emit = @This(); |
| ... | @@ -15,7 +15,7 @@ const Target = std.Target; | ... | @@ -15,7 +15,7 @@ const Target = std.Target; |
| 15 | const assert = std.debug.assert; | 15 | const assert = std.debug.assert; |
| 16 | const Instruction = bits.Instruction; | 16 | const Instruction = bits.Instruction; |
| 17 | const Register = bits.Register; | 17 | const Register = bits.Register; |
| 18 | const log = std.log.scoped(.aarch64_emit); | 18 | const log = std.log.scoped(.aarch32_emit); |
| 19 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; | 19 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; |
| 20 | const CodeGen = @import("CodeGen.zig"); | 20 | const CodeGen = @import("CodeGen.zig"); |
| 21 | 21 | ||
| ... | @@ -100,6 +100,7 @@ pub fn emitMir( | ... | @@ -100,6 +100,7 @@ pub fn emitMir( |
| 100 | 100 | ||
| 101 | .b => try emit.mirBranch(inst), | 101 | .b => try emit.mirBranch(inst), |
| 102 | 102 | ||
| 103 | .undefined_instruction => try emit.mirUndefinedInstruction(), | ||
| 103 | .bkpt => try emit.mirExceptionGeneration(inst), | 104 | .bkpt => try emit.mirExceptionGeneration(inst), |
| 104 | 105 | ||
| 105 | .blx => try emit.mirBranchExchange(inst), | 106 | .blx => try emit.mirBranchExchange(inst), |
| ... | @@ -494,6 +495,10 @@ fn mirBranch(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -494,6 +495,10 @@ fn mirBranch(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 494 | } | 495 | } |
| 495 | } | 496 | } |
| 496 | 497 | ||
| 498 | fn mirUndefinedInstruction(emit: *Emit) !void { | ||
| 499 | try emit.writeInstruction(Instruction.undefinedInstruction()); | ||
| 500 | } | ||
| 501 | |||
| 497 | fn mirExceptionGeneration(emit: *Emit, inst: Mir.Inst.Index) !void { | 502 | fn mirExceptionGeneration(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 498 | const tag = emit.mir.instructions.items(.tag)[inst]; | 503 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 499 | const imm16 = emit.mir.instructions.items(.data)[inst].imm16; | 504 | const imm16 = emit.mir.instructions.items(.data)[inst].imm16; |
src/arch/arm/Mir.zig+2| ... | @@ -35,6 +35,8 @@ pub const Inst = struct { | ... | @@ -35,6 +35,8 @@ pub const Inst = struct { |
| 35 | asr, | 35 | asr, |
| 36 | /// Branch | 36 | /// Branch |
| 37 | b, | 37 | b, |
| 38 | /// Undefined instruction | ||
| 39 | undefined_instruction, | ||
| 38 | /// Breakpoint | 40 | /// Breakpoint |
| 39 | bkpt, | 41 | bkpt, |
| 40 | /// Branch with Link and Exchange | 42 | /// Branch with Link and Exchange |
src/arch/arm/bits.zig+11| ... | @@ -307,6 +307,9 @@ pub const Instruction = union(enum) { | ... | @@ -307,6 +307,9 @@ pub const Instruction = union(enum) { |
| 307 | fixed: u4 = 0b1111, | 307 | fixed: u4 = 0b1111, |
| 308 | cond: u4, | 308 | cond: u4, |
| 309 | }, | 309 | }, |
| 310 | undefined_instruction: packed struct { | ||
| 311 | imm32: u32 = 0xe7ffdefe, | ||
| 312 | }, | ||
| 310 | breakpoint: packed struct { | 313 | breakpoint: packed struct { |
| 311 | imm4: u4, | 314 | imm4: u4, |
| 312 | fixed_1: u4 = 0b0111, | 315 | fixed_1: u4 = 0b0111, |
| ... | @@ -613,6 +616,7 @@ pub const Instruction = union(enum) { | ... | @@ -613,6 +616,7 @@ pub const Instruction = union(enum) { |
| 613 | .branch => |v| @bitCast(u32, v), | 616 | .branch => |v| @bitCast(u32, v), |
| 614 | .branch_exchange => |v| @bitCast(u32, v), | 617 | .branch_exchange => |v| @bitCast(u32, v), |
| 615 | .supervisor_call => |v| @bitCast(u32, v), | 618 | .supervisor_call => |v| @bitCast(u32, v), |
| 619 | .undefined_instruction => |v| v.imm32, | ||
| 616 | .breakpoint => |v| @intCast(u32, v.imm4) | (@intCast(u32, v.fixed_1) << 4) | (@intCast(u32, v.imm12) << 8) | (@intCast(u32, v.fixed_2_and_cond) << 20), | 620 | .breakpoint => |v| @intCast(u32, v.imm4) | (@intCast(u32, v.fixed_1) << 4) | (@intCast(u32, v.imm12) << 8) | (@intCast(u32, v.fixed_2_and_cond) << 20), |
| 617 | }; | 621 | }; |
| 618 | } | 622 | } |
| ... | @@ -890,6 +894,13 @@ pub const Instruction = union(enum) { | ... | @@ -890,6 +894,13 @@ pub const Instruction = union(enum) { |
| 890 | }; | 894 | }; |
| 891 | } | 895 | } |
| 892 | 896 | ||
| 897 | // This instruction has no official mnemonic equivalent so it is public as-is. | ||
| 898 | pub fn undefinedInstruction() Instruction { | ||
| 899 | return Instruction{ | ||
| 900 | .undefined_instruction = .{}, | ||
| 901 | }; | ||
| 902 | } | ||
| 903 | |||
| 893 | fn breakpoint(imm: u16) Instruction { | 904 | fn breakpoint(imm: u16) Instruction { |
| 894 | return Instruction{ | 905 | return Instruction{ |
| 895 | .breakpoint = .{ | 906 | .breakpoint = .{ |
src/arch/riscv64/CodeGen.zig+9| ... | @@ -547,6 +547,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -547,6 +547,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 547 | .bitcast => try self.airBitCast(inst), | 547 | .bitcast => try self.airBitCast(inst), |
| 548 | .block => try self.airBlock(inst), | 548 | .block => try self.airBlock(inst), |
| 549 | .br => try self.airBr(inst), | 549 | .br => try self.airBr(inst), |
| 550 | .trap => try self.airTrap(), | ||
| 550 | .breakpoint => try self.airBreakpoint(), | 551 | .breakpoint => try self.airBreakpoint(), |
| 551 | .ret_addr => try self.airRetAddr(inst), | 552 | .ret_addr => try self.airRetAddr(inst), |
| 552 | .frame_addr => try self.airFrameAddress(inst), | 553 | .frame_addr => try self.airFrameAddress(inst), |
| ... | @@ -1649,6 +1650,14 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1649,6 +1650,14 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 1649 | return self.finishAir(inst, mcv, .{ .none, .none, .none }); | 1650 | return self.finishAir(inst, mcv, .{ .none, .none, .none }); |
| 1650 | } | 1651 | } |
| 1651 | 1652 | ||
| 1653 | fn airTrap(self: *Self) !void { | ||
| 1654 | _ = try self.addInst(.{ | ||
| 1655 | .tag = .unimp, | ||
| 1656 | .data = .{ .nop = {} }, | ||
| 1657 | }); | ||
| 1658 | return self.finishAirBookkeeping(); | ||
| 1659 | } | ||
| 1660 | |||
| 1652 | fn airBreakpoint(self: *Self) !void { | 1661 | fn airBreakpoint(self: *Self) !void { |
| 1653 | _ = try self.addInst(.{ | 1662 | _ = try self.addInst(.{ |
| 1654 | .tag = .ebreak, | 1663 | .tag = .ebreak, |
src/arch/riscv64/Emit.zig+2| ... | @@ -51,6 +51,7 @@ pub fn emitMir( | ... | @@ -51,6 +51,7 @@ pub fn emitMir( |
| 51 | 51 | ||
| 52 | .ebreak => try emit.mirSystem(inst), | 52 | .ebreak => try emit.mirSystem(inst), |
| 53 | .ecall => try emit.mirSystem(inst), | 53 | .ecall => try emit.mirSystem(inst), |
| 54 | .unimp => try emit.mirSystem(inst), | ||
| 54 | 55 | ||
| 55 | .dbg_line => try emit.mirDbgLine(inst), | 56 | .dbg_line => try emit.mirDbgLine(inst), |
| 56 | 57 | ||
| ... | @@ -153,6 +154,7 @@ fn mirSystem(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -153,6 +154,7 @@ fn mirSystem(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 153 | switch (tag) { | 154 | switch (tag) { |
| 154 | .ebreak => try emit.writeInstruction(Instruction.ebreak), | 155 | .ebreak => try emit.writeInstruction(Instruction.ebreak), |
| 155 | .ecall => try emit.writeInstruction(Instruction.ecall), | 156 | .ecall => try emit.writeInstruction(Instruction.ecall), |
| 157 | .unimp => try emit.writeInstruction(Instruction.unimp), | ||
| 156 | else => unreachable, | 158 | else => unreachable, |
| 157 | } | 159 | } |
| 158 | } | 160 | } |
src/arch/riscv64/Mir.zig+1| ... | @@ -32,6 +32,7 @@ pub const Inst = struct { | ... | @@ -32,6 +32,7 @@ pub const Inst = struct { |
| 32 | dbg_epilogue_begin, | 32 | dbg_epilogue_begin, |
| 33 | /// Pseudo-instruction: Update debug line | 33 | /// Pseudo-instruction: Update debug line |
| 34 | dbg_line, | 34 | dbg_line, |
| 35 | unimp, | ||
| 35 | ebreak, | 36 | ebreak, |
| 36 | ecall, | 37 | ecall, |
| 37 | jalr, | 38 | jalr, |
src/arch/riscv64/bits.zig+1| ... | @@ -380,6 +380,7 @@ pub const Instruction = union(enum) { | ... | @@ -380,6 +380,7 @@ pub const Instruction = union(enum) { |
| 380 | 380 | ||
| 381 | pub const ecall = iType(0b1110011, 0b000, .zero, .zero, 0x000); | 381 | pub const ecall = iType(0b1110011, 0b000, .zero, .zero, 0x000); |
| 382 | pub const ebreak = iType(0b1110011, 0b000, .zero, .zero, 0x001); | 382 | pub const ebreak = iType(0b1110011, 0b000, .zero, .zero, 0x001); |
| 383 | pub const unimp = iType(0, 0, .zero, .zero, 0); | ||
| 383 | }; | 384 | }; |
| 384 | 385 | ||
| 385 | pub const Register = enum(u6) { | 386 | pub const Register = enum(u6) { |
src/arch/sparc64/CodeGen.zig+16| ... | @@ -562,6 +562,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -562,6 +562,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 562 | .bitcast => try self.airBitCast(inst), | 562 | .bitcast => try self.airBitCast(inst), |
| 563 | .block => try self.airBlock(inst), | 563 | .block => try self.airBlock(inst), |
| 564 | .br => try self.airBr(inst), | 564 | .br => try self.airBr(inst), |
| 565 | .trap => try self.airTrap(), | ||
| 565 | .breakpoint => try self.airBreakpoint(), | 566 | .breakpoint => try self.airBreakpoint(), |
| 566 | .ret_addr => @panic("TODO try self.airRetAddr(inst)"), | 567 | .ret_addr => @panic("TODO try self.airRetAddr(inst)"), |
| 567 | .frame_addr => @panic("TODO try self.airFrameAddress(inst)"), | 568 | .frame_addr => @panic("TODO try self.airFrameAddress(inst)"), |
| ... | @@ -1156,6 +1157,21 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1156,6 +1157,21 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1156 | return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); | 1157 | return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); |
| 1157 | } | 1158 | } |
| 1158 | 1159 | ||
| 1160 | fn airTrap(self: *Self) !void { | ||
| 1161 | // ta 0x05 | ||
| 1162 | _ = try self.addInst(.{ | ||
| 1163 | .tag = .tcc, | ||
| 1164 | .data = .{ | ||
| 1165 | .trap = .{ | ||
| 1166 | .is_imm = true, | ||
| 1167 | .cond = .al, | ||
| 1168 | .rs2_or_imm = .{ .imm = 0x05 }, | ||
| 1169 | }, | ||
| 1170 | }, | ||
| 1171 | }); | ||
| 1172 | return self.finishAirBookkeeping(); | ||
| 1173 | } | ||
| 1174 | |||
| 1159 | fn airBreakpoint(self: *Self) !void { | 1175 | fn airBreakpoint(self: *Self) !void { |
| 1160 | // ta 0x01 | 1176 | // ta 0x01 |
| 1161 | _ = try self.addInst(.{ | 1177 | _ = try self.addInst(.{ |
src/arch/wasm/CodeGen.zig+7| ... | @@ -1827,6 +1827,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -1827,6 +1827,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1827 | .arg => func.airArg(inst), | 1827 | .arg => func.airArg(inst), |
| 1828 | .bitcast => func.airBitcast(inst), | 1828 | .bitcast => func.airBitcast(inst), |
| 1829 | .block => func.airBlock(inst), | 1829 | .block => func.airBlock(inst), |
| 1830 | .trap => func.airTrap(inst), | ||
| 1830 | .breakpoint => func.airBreakpoint(inst), | 1831 | .breakpoint => func.airBreakpoint(inst), |
| 1831 | .br => func.airBr(inst), | 1832 | .br => func.airBr(inst), |
| 1832 | .bool_to_int => func.airBoolToInt(inst), | 1833 | .bool_to_int => func.airBoolToInt(inst), |
| ... | @@ -3287,9 +3288,15 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3287,9 +3288,15 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3287 | func.finishAir(inst, result, &.{ty_op.operand}); | 3288 | func.finishAir(inst, result, &.{ty_op.operand}); |
| 3288 | } | 3289 | } |
| 3289 | 3290 | ||
| 3291 | fn airTrap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ||
| 3292 | try func.addTag(.@"unreachable"); | ||
| 3293 | func.finishAir(inst, .none, &.{}); | ||
| 3294 | } | ||
| 3295 | |||
| 3290 | fn airBreakpoint(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 3296 | fn airBreakpoint(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3291 | // unsupported by wasm itfunc. Can be implemented once we support DWARF | 3297 | // unsupported by wasm itfunc. Can be implemented once we support DWARF |
| 3292 | // for wasm | 3298 | // for wasm |
| 3299 | try func.addTag(.@"unreachable"); | ||
| 3293 | func.finishAir(inst, .none, &.{}); | 3300 | func.finishAir(inst, .none, &.{}); |
| 3294 | } | 3301 | } |
| 3295 | 3302 |
src/arch/x86_64/CodeGen.zig+10| ... | @@ -634,6 +634,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -634,6 +634,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 634 | .bitcast => try self.airBitCast(inst), | 634 | .bitcast => try self.airBitCast(inst), |
| 635 | .block => try self.airBlock(inst), | 635 | .block => try self.airBlock(inst), |
| 636 | .br => try self.airBr(inst), | 636 | .br => try self.airBr(inst), |
| 637 | .trap => try self.airTrap(), | ||
| 637 | .breakpoint => try self.airBreakpoint(), | 638 | .breakpoint => try self.airBreakpoint(), |
| 638 | .ret_addr => try self.airRetAddr(inst), | 639 | .ret_addr => try self.airRetAddr(inst), |
| 639 | .frame_addr => try self.airFrameAddress(inst), | 640 | .frame_addr => try self.airFrameAddress(inst), |
| ... | @@ -3913,6 +3914,15 @@ fn genVarDbgInfo( | ... | @@ -3913,6 +3914,15 @@ fn genVarDbgInfo( |
| 3913 | } | 3914 | } |
| 3914 | } | 3915 | } |
| 3915 | 3916 | ||
| 3917 | fn airTrap(self: *Self) !void { | ||
| 3918 | _ = try self.addInst(.{ | ||
| 3919 | .tag = .ud, | ||
| 3920 | .ops = Mir.Inst.Ops.encode(.{}), | ||
| 3921 | .data = undefined, | ||
| 3922 | }); | ||
| 3923 | return self.finishAirBookkeeping(); | ||
| 3924 | } | ||
| 3925 | |||
| 3916 | fn airBreakpoint(self: *Self) !void { | 3926 | fn airBreakpoint(self: *Self) !void { |
| 3917 | _ = try self.addInst(.{ | 3927 | _ = try self.addInst(.{ |
| 3918 | .tag = .interrupt, | 3928 | .tag = .interrupt, |
src/arch/x86_64/Emit.zig+7| ... | @@ -166,6 +166,7 @@ pub fn lowerMir(emit: *Emit) InnerError!void { | ... | @@ -166,6 +166,7 @@ pub fn lowerMir(emit: *Emit) InnerError!void { |
| 166 | 166 | ||
| 167 | .@"test" => try emit.mirTest(inst), | 167 | .@"test" => try emit.mirTest(inst), |
| 168 | 168 | ||
| 169 | .ud => try emit.mirUndefinedInstruction(), | ||
| 169 | .interrupt => try emit.mirInterrupt(inst), | 170 | .interrupt => try emit.mirInterrupt(inst), |
| 170 | .nop => {}, // just skip it | 171 | .nop => {}, // just skip it |
| 171 | 172 | ||
| ... | @@ -234,6 +235,10 @@ fn fixupRelocs(emit: *Emit) InnerError!void { | ... | @@ -234,6 +235,10 @@ fn fixupRelocs(emit: *Emit) InnerError!void { |
| 234 | } | 235 | } |
| 235 | } | 236 | } |
| 236 | 237 | ||
| 238 | fn mirUndefinedInstruction(emit: *Emit) InnerError!void { | ||
| 239 | return lowerToZoEnc(.ud2, emit.code); | ||
| 240 | } | ||
| 241 | |||
| 237 | fn mirInterrupt(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | 242 | fn mirInterrupt(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 238 | const tag = emit.mir.instructions.items(.tag)[inst]; | 243 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 239 | assert(tag == .interrupt); | 244 | assert(tag == .interrupt); |
| ... | @@ -1279,6 +1284,7 @@ const Tag = enum { | ... | @@ -1279,6 +1284,7 @@ const Tag = enum { |
| 1279 | push, | 1284 | push, |
| 1280 | pop, | 1285 | pop, |
| 1281 | @"test", | 1286 | @"test", |
| 1287 | ud2, | ||
| 1282 | int3, | 1288 | int3, |
| 1283 | nop, | 1289 | nop, |
| 1284 | imul, | 1290 | imul, |
| ... | @@ -1571,6 +1577,7 @@ inline fn getOpCode(tag: Tag, enc: Encoding, is_one_byte: bool) OpCode { | ... | @@ -1571,6 +1577,7 @@ inline fn getOpCode(tag: Tag, enc: Encoding, is_one_byte: bool) OpCode { |
| 1571 | .zo => return switch (tag) { | 1577 | .zo => return switch (tag) { |
| 1572 | .ret_near => OpCode.init(&.{0xc3}), | 1578 | .ret_near => OpCode.init(&.{0xc3}), |
| 1573 | .ret_far => OpCode.init(&.{0xcb}), | 1579 | .ret_far => OpCode.init(&.{0xcb}), |
| 1580 | .ud2 => OpCode.init(&.{ 0x0F, 0x0B }), | ||
| 1574 | .int3 => OpCode.init(&.{0xcc}), | 1581 | .int3 => OpCode.init(&.{0xcc}), |
| 1575 | .nop => OpCode.init(&.{0x90}), | 1582 | .nop => OpCode.init(&.{0x90}), |
| 1576 | .syscall => OpCode.init(&.{ 0x0f, 0x05 }), | 1583 | .syscall => OpCode.init(&.{ 0x0f, 0x05 }), |
src/arch/x86_64/Mir.zig+3| ... | @@ -329,6 +329,9 @@ pub const Inst = struct { | ... | @@ -329,6 +329,9 @@ pub const Inst = struct { |
| 329 | /// TODO handle more cases | 329 | /// TODO handle more cases |
| 330 | @"test", | 330 | @"test", |
| 331 | 331 | ||
| 332 | /// Undefined Instruction | ||
| 333 | ud, | ||
| 334 | |||
| 332 | /// Breakpoint form: | 335 | /// Breakpoint form: |
| 333 | /// 0b00 int3 | 336 | /// 0b00 int3 |
| 334 | interrupt, | 337 | interrupt, |
src/codegen/c.zig+6| ... | @@ -2741,6 +2741,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -2741,6 +2741,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2741 | .const_ty => unreachable, // excluded from function bodies | 2741 | .const_ty => unreachable, // excluded from function bodies |
| 2742 | .arg => try airArg(f, inst), | 2742 | .arg => try airArg(f, inst), |
| 2743 | 2743 | ||
| 2744 | .trap => try airTrap(f.object.writer()), | ||
| 2744 | .breakpoint => try airBreakpoint(f.object.writer()), | 2745 | .breakpoint => try airBreakpoint(f.object.writer()), |
| 2745 | .ret_addr => try airRetAddr(f, inst), | 2746 | .ret_addr => try airRetAddr(f, inst), |
| 2746 | .frame_addr => try airFrameAddress(f, inst), | 2747 | .frame_addr => try airFrameAddress(f, inst), |
| ... | @@ -4428,6 +4429,11 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4428,6 +4429,11 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4428 | return local; | 4429 | return local; |
| 4429 | } | 4430 | } |
| 4430 | 4431 | ||
| 4432 | fn airTrap(writer: anytype) !CValue { | ||
| 4433 | try writer.writeAll("zig_trap();\n"); | ||
| 4434 | return .none; | ||
| 4435 | } | ||
| 4436 | |||
| 4431 | fn airBreakpoint(writer: anytype) !CValue { | 4437 | fn airBreakpoint(writer: anytype) !CValue { |
| 4432 | try writer.writeAll("zig_breakpoint();\n"); | 4438 | try writer.writeAll("zig_breakpoint();\n"); |
| 4433 | return .none; | 4439 | return .none; |
src/codegen/llvm.zig+8| ... | @@ -4590,6 +4590,7 @@ pub const FuncGen = struct { | ... | @@ -4590,6 +4590,7 @@ pub const FuncGen = struct { |
| 4590 | .block => try self.airBlock(inst), | 4590 | .block => try self.airBlock(inst), |
| 4591 | .br => try self.airBr(inst), | 4591 | .br => try self.airBr(inst), |
| 4592 | .switch_br => try self.airSwitchBr(inst), | 4592 | .switch_br => try self.airSwitchBr(inst), |
| 4593 | .trap => try self.airTrap(inst), | ||
| 4593 | .breakpoint => try self.airBreakpoint(inst), | 4594 | .breakpoint => try self.airBreakpoint(inst), |
| 4594 | .ret_addr => try self.airRetAddr(inst), | 4595 | .ret_addr => try self.airRetAddr(inst), |
| 4595 | .frame_addr => try self.airFrameAddress(inst), | 4596 | .frame_addr => try self.airFrameAddress(inst), |
| ... | @@ -8256,6 +8257,13 @@ pub const FuncGen = struct { | ... | @@ -8256,6 +8257,13 @@ pub const FuncGen = struct { |
| 8256 | return fg.load(ptr, ptr_ty); | 8257 | return fg.load(ptr, ptr_ty); |
| 8257 | } | 8258 | } |
| 8258 | 8259 | ||
| 8260 | fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | ||
| 8261 | _ = inst; | ||
| 8262 | const llvm_fn = self.getIntrinsic("llvm.trap", &.{}); | ||
| 8263 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .Cold, .Auto, ""); | ||
| 8264 | return null; | ||
| 8265 | } | ||
| 8266 | |||
| 8259 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8267 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8260 | _ = inst; | 8268 | _ = inst; |
| 8261 | const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); | 8269 | const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); |
src/print_air.zig+1| ... | @@ -194,6 +194,7 @@ const Writer = struct { | ... | @@ -194,6 +194,7 @@ const Writer = struct { |
| 194 | .c_va_end, | 194 | .c_va_end, |
| 195 | => try w.writeUnOp(s, inst), | 195 | => try w.writeUnOp(s, inst), |
| 196 | 196 | ||
| 197 | .trap, | ||
| 197 | .breakpoint, | 198 | .breakpoint, |
| 198 | .unreach, | 199 | .unreach, |
| 199 | .ret_addr, | 200 | .ret_addr, |
src/print_zir.zig+2-1| ... | @@ -196,7 +196,6 @@ const Writer = struct { | ... | @@ -196,7 +196,6 @@ const Writer = struct { |
| 196 | .error_name, | 196 | .error_name, |
| 197 | .panic, | 197 | .panic, |
| 198 | .panic_comptime, | 198 | .panic_comptime, |
| 199 | .set_cold, | ||
| 200 | .set_runtime_safety, | 199 | .set_runtime_safety, |
| 201 | .sqrt, | 200 | .sqrt, |
| 202 | .sin, | 201 | .sin, |
| ... | @@ -411,6 +410,7 @@ const Writer = struct { | ... | @@ -411,6 +410,7 @@ const Writer = struct { |
| 411 | .alloc_inferred_comptime_mut, | 410 | .alloc_inferred_comptime_mut, |
| 412 | .ret_ptr, | 411 | .ret_ptr, |
| 413 | .ret_type, | 412 | .ret_type, |
| 413 | .trap, | ||
| 414 | => try self.writeNode(stream, inst), | 414 | => try self.writeNode(stream, inst), |
| 415 | 415 | ||
| 416 | .error_value, | 416 | .error_value, |
| ... | @@ -503,6 +503,7 @@ const Writer = struct { | ... | @@ -503,6 +503,7 @@ const Writer = struct { |
| 503 | .fence, | 503 | .fence, |
| 504 | .set_float_mode, | 504 | .set_float_mode, |
| 505 | .set_align_stack, | 505 | .set_align_stack, |
| 506 | .set_cold, | ||
| 506 | .wasm_memory_size, | 507 | .wasm_memory_size, |
| 507 | .error_to_int, | 508 | .error_to_int, |
| 508 | .int_to_error, | 509 | .int_to_error, |