| author | |
| committer | |
| log | 069c83d58cebba88275ee76ba01fabcd8e964573 |
| tree | ab7e52f307bd23869e2461189383522dc64f42de |
| parent | 86b92809635607ff357ce96902e2aaf83c3fd029 |
After a discussion about language specs, this seems like the best way to
go, because it's simpler to reason about both for humans and compilers.
The `bitcast_result_ptr` ZIR instruction is no longer needed.
This commit also implements writing enums, arrays, and vectors to
virtual memory at compile-time.
This unlocked some more of compiler-rt being able to build, which
in turn unlocks saturating arithmetic behavior tests.
There was also a memory leak in the comptime closure system which is now
fixed.10 files changed, 140 insertions(+), 153 deletions(-)
lib/std/special/compiler_rt.zig+75-75| ... | @@ -81,6 +81,81 @@ comptime { | ... | @@ -81,6 +81,81 @@ comptime { |
| 81 | @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); | 81 | @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | if (builtin.os.tag == .windows) { | ||
| 85 | // Default stack-probe functions emitted by LLVM | ||
| 86 | if (is_mingw) { | ||
| 87 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | ||
| 88 | @export(_chkstk, .{ .name = "_alloca", .linkage = strong_linkage }); | ||
| 89 | const ___chkstk_ms = @import("compiler_rt/stack_probe.zig").___chkstk_ms; | ||
| 90 | @export(___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = strong_linkage }); | ||
| 91 | } else if (!builtin.link_libc) { | ||
| 92 | // This symbols are otherwise exported by MSVCRT.lib | ||
| 93 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | ||
| 94 | @export(_chkstk, .{ .name = "_chkstk", .linkage = strong_linkage }); | ||
| 95 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | ||
| 96 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | ||
| 97 | } | ||
| 98 | |||
| 99 | switch (arch) { | ||
| 100 | .i386 => { | ||
| 101 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | ||
| 102 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | ||
| 103 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | ||
| 104 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | ||
| 105 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | ||
| 106 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | ||
| 107 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 108 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 109 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | ||
| 110 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 111 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | ||
| 112 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 113 | }, | ||
| 114 | .x86_64 => { | ||
| 115 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | ||
| 116 | // that LLVM expects compiler-rt to have. | ||
| 117 | const __divti3_windows_x86_64 = @import("compiler_rt/divti3.zig").__divti3_windows_x86_64; | ||
| 118 | @export(__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = linkage }); | ||
| 119 | const __modti3_windows_x86_64 = @import("compiler_rt/modti3.zig").__modti3_windows_x86_64; | ||
| 120 | @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = linkage }); | ||
| 121 | const __multi3_windows_x86_64 = @import("compiler_rt/multi3.zig").__multi3_windows_x86_64; | ||
| 122 | @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = linkage }); | ||
| 123 | const __udivti3_windows_x86_64 = @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64; | ||
| 124 | @export(__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 125 | const __udivmodti4_windows_x86_64 = @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64; | ||
| 126 | @export(__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 127 | const __umodti3_windows_x86_64 = @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64; | ||
| 128 | @export(__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 129 | }, | ||
| 130 | else => {}, | ||
| 131 | } | ||
| 132 | if (arch.isAARCH64()) { | ||
| 133 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | ||
| 134 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | ||
| 135 | const __divti3_windows = @import("compiler_rt/divti3.zig").__divti3; | ||
| 136 | @export(__divti3_windows, .{ .name = "__divti3", .linkage = linkage }); | ||
| 137 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | ||
| 138 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | ||
| 139 | const __udivti3_windows = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 140 | @export(__udivti3_windows, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 141 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | ||
| 142 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 143 | } | ||
| 144 | } else { | ||
| 145 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | ||
| 146 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | ||
| 147 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | ||
| 148 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | ||
| 149 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | ||
| 150 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | ||
| 151 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 152 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 153 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | ||
| 154 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 155 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | ||
| 156 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 157 | } | ||
| 158 | |||
| 84 | if (!builtin.zig_is_stage2) { | 159 | if (!builtin.zig_is_stage2) { |
| 85 | if (!long_double_is_f128) { | 160 | if (!long_double_is_f128) { |
| 86 | // TODO implement these | 161 | // TODO implement these |
| ... | @@ -552,81 +627,6 @@ comptime { | ... | @@ -552,81 +627,6 @@ comptime { |
| 552 | @export(__unordtf2, .{ .name = "__unordkf2", .linkage = linkage }); | 627 | @export(__unordtf2, .{ .name = "__unordkf2", .linkage = linkage }); |
| 553 | } | 628 | } |
| 554 | 629 | ||
| 555 | if (builtin.os.tag == .windows) { | ||
| 556 | // Default stack-probe functions emitted by LLVM | ||
| 557 | if (is_mingw) { | ||
| 558 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | ||
| 559 | @export(_chkstk, .{ .name = "_alloca", .linkage = strong_linkage }); | ||
| 560 | const ___chkstk_ms = @import("compiler_rt/stack_probe.zig").___chkstk_ms; | ||
| 561 | @export(___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = strong_linkage }); | ||
| 562 | } else if (!builtin.link_libc) { | ||
| 563 | // This symbols are otherwise exported by MSVCRT.lib | ||
| 564 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | ||
| 565 | @export(_chkstk, .{ .name = "_chkstk", .linkage = strong_linkage }); | ||
| 566 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | ||
| 567 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | ||
| 568 | } | ||
| 569 | |||
| 570 | switch (arch) { | ||
| 571 | .i386 => { | ||
| 572 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | ||
| 573 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | ||
| 574 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | ||
| 575 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | ||
| 576 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | ||
| 577 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | ||
| 578 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 579 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 580 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | ||
| 581 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 582 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | ||
| 583 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 584 | }, | ||
| 585 | .x86_64 => { | ||
| 586 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | ||
| 587 | // that LLVM expects compiler-rt to have. | ||
| 588 | const __divti3_windows_x86_64 = @import("compiler_rt/divti3.zig").__divti3_windows_x86_64; | ||
| 589 | @export(__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = linkage }); | ||
| 590 | const __modti3_windows_x86_64 = @import("compiler_rt/modti3.zig").__modti3_windows_x86_64; | ||
| 591 | @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = linkage }); | ||
| 592 | const __multi3_windows_x86_64 = @import("compiler_rt/multi3.zig").__multi3_windows_x86_64; | ||
| 593 | @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = linkage }); | ||
| 594 | const __udivti3_windows_x86_64 = @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64; | ||
| 595 | @export(__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 596 | const __udivmodti4_windows_x86_64 = @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64; | ||
| 597 | @export(__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 598 | const __umodti3_windows_x86_64 = @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64; | ||
| 599 | @export(__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 600 | }, | ||
| 601 | else => {}, | ||
| 602 | } | ||
| 603 | if (arch.isAARCH64()) { | ||
| 604 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | ||
| 605 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | ||
| 606 | const __divti3_windows = @import("compiler_rt/divti3.zig").__divti3; | ||
| 607 | @export(__divti3_windows, .{ .name = "__divti3", .linkage = linkage }); | ||
| 608 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | ||
| 609 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | ||
| 610 | const __udivti3_windows = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 611 | @export(__udivti3_windows, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 612 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | ||
| 613 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 614 | } | ||
| 615 | } else { | ||
| 616 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | ||
| 617 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | ||
| 618 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | ||
| 619 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | ||
| 620 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | ||
| 621 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | ||
| 622 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 623 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 624 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | ||
| 625 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 626 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | ||
| 627 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 628 | } | ||
| 629 | |||
| 630 | _ = @import("compiler_rt/atomics.zig"); | 630 | _ = @import("compiler_rt/atomics.zig"); |
| 631 | 631 | ||
| 632 | @export(fmaq, .{ .name = "fmaq", .linkage = linkage }); | 632 | @export(fmaq, .{ .name = "fmaq", .linkage = linkage }); |
src/AstGen.zig+20-37| ... | @@ -276,17 +276,30 @@ fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zi | ... | @@ -276,17 +276,30 @@ fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zi |
| 276 | return expr(gz, scope, coerced_type_rl, type_node); | 276 | return expr(gz, scope, coerced_type_rl, type_node); |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | fn reachableTypeExpr( | ||
| 280 | gz: *GenZir, | ||
| 281 | scope: *Scope, | ||
| 282 | type_node: Ast.Node.Index, | ||
| 283 | reachable_node: Ast.Node.Index, | ||
| 284 | ) InnerError!Zir.Inst.Ref { | ||
| 285 | const prev_force_comptime = gz.force_comptime; | ||
| 286 | gz.force_comptime = true; | ||
| 287 | defer gz.force_comptime = prev_force_comptime; | ||
| 288 | |||
| 289 | return reachableExpr(gz, scope, coerced_type_rl, type_node, reachable_node); | ||
| 290 | } | ||
| 291 | |||
| 279 | /// Same as `expr` but fails with a compile error if the result type is `noreturn`. | 292 | /// Same as `expr` but fails with a compile error if the result type is `noreturn`. |
| 280 | fn reachableExpr( | 293 | fn reachableExpr( |
| 281 | gz: *GenZir, | 294 | gz: *GenZir, |
| 282 | scope: *Scope, | 295 | scope: *Scope, |
| 283 | rl: ResultLoc, | 296 | rl: ResultLoc, |
| 284 | node: Ast.Node.Index, | 297 | node: Ast.Node.Index, |
| 285 | src_node: Ast.Node.Index, | 298 | reachable_node: Ast.Node.Index, |
| 286 | ) InnerError!Zir.Inst.Ref { | 299 | ) InnerError!Zir.Inst.Ref { |
| 287 | const result_inst = try expr(gz, scope, rl, node); | 300 | const result_inst = try expr(gz, scope, rl, node); |
| 288 | if (gz.refIsNoReturn(result_inst)) { | 301 | if (gz.refIsNoReturn(result_inst)) { |
| 289 | return gz.astgen.failNodeNotes(src_node, "unreachable code", .{}, &[_]u32{ | 302 | return gz.astgen.failNodeNotes(reachable_node, "unreachable code", .{}, &[_]u32{ |
| 290 | try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}), | 303 | try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}), |
| 291 | }); | 304 | }); |
| 292 | } | 305 | } |
| ... | @@ -2040,7 +2053,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner | ... | @@ -2040,7 +2053,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2040 | .as_node, | 2053 | .as_node, |
| 2041 | .bit_and, | 2054 | .bit_and, |
| 2042 | .bitcast, | 2055 | .bitcast, |
| 2043 | .bitcast_result_ptr, | ||
| 2044 | .bit_or, | 2056 | .bit_or, |
| 2045 | .block, | 2057 | .block, |
| 2046 | .block_inline, | 2058 | .block_inline, |
| ... | @@ -7160,42 +7172,13 @@ fn bitCast( | ... | @@ -7160,42 +7172,13 @@ fn bitCast( |
| 7160 | lhs: Ast.Node.Index, | 7172 | lhs: Ast.Node.Index, |
| 7161 | rhs: Ast.Node.Index, | 7173 | rhs: Ast.Node.Index, |
| 7162 | ) InnerError!Zir.Inst.Ref { | 7174 | ) InnerError!Zir.Inst.Ref { |
| 7163 | const astgen = gz.astgen; | 7175 | const dest_type = try reachableTypeExpr(gz, scope, lhs, node); |
| 7164 | const dest_type = try typeExpr(gz, scope, lhs); | 7176 | const operand = try reachableExpr(gz, scope, .none, rhs, node); |
| 7165 | switch (rl) { | 7177 | const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{ |
| 7166 | .none, .discard, .ty, .coerced_ty => { | ||
| 7167 | const operand = try expr(gz, scope, .none, rhs); | ||
| 7168 | const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{ | ||
| 7169 | .lhs = dest_type, | ||
| 7170 | .rhs = operand, | ||
| 7171 | }); | ||
| 7172 | return rvalue(gz, rl, result, node); | ||
| 7173 | }, | ||
| 7174 | .ref => { | ||
| 7175 | return astgen.failNode(node, "cannot take address of `@bitCast` result", .{}); | ||
| 7176 | }, | ||
| 7177 | .ptr, .inferred_ptr => |result_ptr| { | ||
| 7178 | return bitCastRlPtr(gz, scope, node, dest_type, result_ptr, rhs); | ||
| 7179 | }, | ||
| 7180 | .block_ptr => |block| { | ||
| 7181 | return bitCastRlPtr(gz, scope, node, dest_type, block.rl_ptr, rhs); | ||
| 7182 | }, | ||
| 7183 | } | ||
| 7184 | } | ||
| 7185 | |||
| 7186 | fn bitCastRlPtr( | ||
| 7187 | gz: *GenZir, | ||
| 7188 | scope: *Scope, | ||
| 7189 | node: Ast.Node.Index, | ||
| 7190 | dest_type: Zir.Inst.Ref, | ||
| 7191 | result_ptr: Zir.Inst.Ref, | ||
| 7192 | rhs: Ast.Node.Index, | ||
| 7193 | ) InnerError!Zir.Inst.Ref { | ||
| 7194 | const casted_result_ptr = try gz.addPlNode(.bitcast_result_ptr, node, Zir.Inst.Bin{ | ||
| 7195 | .lhs = dest_type, | 7178 | .lhs = dest_type, |
| 7196 | .rhs = result_ptr, | 7179 | .rhs = operand, |
| 7197 | }); | 7180 | }); |
| 7198 | return expr(gz, scope, .{ .ptr = casted_result_ptr }, rhs); | 7181 | return rvalue(gz, rl, result, node); |
| 7199 | } | 7182 | } |
| 7200 | 7183 | ||
| 7201 | fn typeOf( | 7184 | fn typeOf( |
src/Module.zig+1| ... | @@ -317,6 +317,7 @@ pub const WipCaptureScope = struct { | ... | @@ -317,6 +317,7 @@ pub const WipCaptureScope = struct { |
| 317 | assert(!self.finalized); | 317 | assert(!self.finalized); |
| 318 | // use a temp to avoid unintentional aliasing due to RLS | 318 | // use a temp to avoid unintentional aliasing due to RLS |
| 319 | const tmp = try self.scope.captures.clone(self.perm_arena); | 319 | const tmp = try self.scope.captures.clone(self.perm_arena); |
| 320 | self.scope.captures.deinit(self.gpa); | ||
| 320 | self.scope.captures = tmp; | 321 | self.scope.captures = tmp; |
| 321 | self.finalized = true; | 322 | self.finalized = true; |
| 322 | } | 323 | } |
src/Sema.zig-7| ... | @@ -513,7 +513,6 @@ pub fn analyzeBody( | ... | @@ -513,7 +513,6 @@ pub fn analyzeBody( |
| 513 | .bit_not => try sema.zirBitNot(block, inst), | 513 | .bit_not => try sema.zirBitNot(block, inst), |
| 514 | .bit_or => try sema.zirBitwise(block, inst, .bit_or), | 514 | .bit_or => try sema.zirBitwise(block, inst, .bit_or), |
| 515 | .bitcast => try sema.zirBitcast(block, inst), | 515 | .bitcast => try sema.zirBitcast(block, inst), |
| 516 | .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst), | ||
| 517 | .suspend_block => try sema.zirSuspendBlock(block, inst), | 516 | .suspend_block => try sema.zirSuspendBlock(block, inst), |
| 518 | .bool_not => try sema.zirBoolNot(block, inst), | 517 | .bool_not => try sema.zirBoolNot(block, inst), |
| 519 | .bool_br_and => try sema.zirBoolBr(block, inst, false), | 518 | .bool_br_and => try sema.zirBoolBr(block, inst, false), |
| ... | @@ -1385,12 +1384,6 @@ pub fn resolveInstValue( | ... | @@ -1385,12 +1384,6 @@ pub fn resolveInstValue( |
| 1385 | }; | 1384 | }; |
| 1386 | } | 1385 | } |
| 1387 | 1386 | ||
| 1388 | fn zirBitcastResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | ||
| 1389 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | ||
| 1390 | const src = inst_data.src(); | ||
| 1391 | return sema.fail(block, src, "TODO implement zir_sema.zirBitcastResultPtr", .{}); | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 1387 | fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 1395 | const tracy = trace(@src()); | 1388 | const tracy = trace(@src()); |
| 1396 | defer tracy.end(); | 1389 | defer tracy.end(); |
src/Zir.zig-6| ... | @@ -240,10 +240,6 @@ pub const Inst = struct { | ... | @@ -240,10 +240,6 @@ pub const Inst = struct { |
| 240 | /// Reinterpret the memory representation of a value as a different type. | 240 | /// Reinterpret the memory representation of a value as a different type. |
| 241 | /// Uses the pl_node field with payload `Bin`. | 241 | /// Uses the pl_node field with payload `Bin`. |
| 242 | bitcast, | 242 | bitcast, |
| 243 | /// A typed result location pointer is bitcasted to a new result location pointer. | ||
| 244 | /// The new result location pointer has an inferred type. | ||
| 245 | /// Uses the pl_node field with payload `Bin`. | ||
| 246 | bitcast_result_ptr, | ||
| 247 | /// Bitwise NOT. `~` | 243 | /// Bitwise NOT. `~` |
| 248 | /// Uses `un_node`. | 244 | /// Uses `un_node`. |
| 249 | bit_not, | 245 | bit_not, |
| ... | @@ -977,7 +973,6 @@ pub const Inst = struct { | ... | @@ -977,7 +973,6 @@ pub const Inst = struct { |
| 977 | .as_node, | 973 | .as_node, |
| 978 | .bit_and, | 974 | .bit_and, |
| 979 | .bitcast, | 975 | .bitcast, |
| 980 | .bitcast_result_ptr, | ||
| 981 | .bit_or, | 976 | .bit_or, |
| 982 | .block, | 977 | .block, |
| 983 | .block_inline, | 978 | .block_inline, |
| ... | @@ -1235,7 +1230,6 @@ pub const Inst = struct { | ... | @@ -1235,7 +1230,6 @@ pub const Inst = struct { |
| 1235 | .as_node = .pl_node, | 1230 | .as_node = .pl_node, |
| 1236 | .bit_and = .pl_node, | 1231 | .bit_and = .pl_node, |
| 1237 | .bitcast = .pl_node, | 1232 | .bitcast = .pl_node, |
| 1238 | .bitcast_result_ptr = .pl_node, | ||
| 1239 | .bit_not = .un_node, | 1233 | .bit_not = .un_node, |
| 1240 | .bit_or = .pl_node, | 1234 | .bit_or = .pl_node, |
| 1241 | .block = .pl_node, | 1235 | .block = .pl_node, |
src/print_zir.zig-1| ... | @@ -349,7 +349,6 @@ const Writer = struct { | ... | @@ -349,7 +349,6 @@ const Writer = struct { |
| 349 | .reduce, | 349 | .reduce, |
| 350 | .atomic_load, | 350 | .atomic_load, |
| 351 | .bitcast, | 351 | .bitcast, |
| 352 | .bitcast_result_ptr, | ||
| 353 | .vector_type, | 352 | .vector_type, |
| 354 | .maximum, | 353 | .maximum, |
| 355 | .minimum, | 354 | .minimum, |
src/value.zig+21| ... | @@ -1015,6 +1015,14 @@ pub const Value = extern union { | ... | @@ -1015,6 +1015,14 @@ pub const Value = extern union { |
| 1015 | const bits = ty.intInfo(target).bits; | 1015 | const bits = ty.intInfo(target).bits; |
| 1016 | bigint.writeTwosComplement(buffer, bits, target.cpu.arch.endian()); | 1016 | bigint.writeTwosComplement(buffer, bits, target.cpu.arch.endian()); |
| 1017 | }, | 1017 | }, |
| 1018 | .Enum => { | ||
| 1019 | var enum_buffer: Payload.U64 = undefined; | ||
| 1020 | const int_val = val.enumToInt(ty, &enum_buffer); | ||
| 1021 | var bigint_buffer: BigIntSpace = undefined; | ||
| 1022 | const bigint = int_val.toBigInt(&bigint_buffer); | ||
| 1023 | const bits = ty.intInfo(target).bits; | ||
| 1024 | bigint.writeTwosComplement(buffer, bits, target.cpu.arch.endian()); | ||
| 1025 | }, | ||
| 1018 | .Float => switch (ty.floatBits(target)) { | 1026 | .Float => switch (ty.floatBits(target)) { |
| 1019 | 16 => return floatWriteToMemory(f16, val.toFloat(f16), target, buffer), | 1027 | 16 => return floatWriteToMemory(f16, val.toFloat(f16), target, buffer), |
| 1020 | 32 => return floatWriteToMemory(f32, val.toFloat(f32), target, buffer), | 1028 | 32 => return floatWriteToMemory(f32, val.toFloat(f32), target, buffer), |
| ... | @@ -1022,6 +1030,19 @@ pub const Value = extern union { | ... | @@ -1022,6 +1030,19 @@ pub const Value = extern union { |
| 1022 | 128 => return floatWriteToMemory(f128, val.toFloat(f128), target, buffer), | 1030 | 128 => return floatWriteToMemory(f128, val.toFloat(f128), target, buffer), |
| 1023 | else => unreachable, | 1031 | else => unreachable, |
| 1024 | }, | 1032 | }, |
| 1033 | .Array, .Vector => { | ||
| 1034 | const len = ty.arrayLen(); | ||
| 1035 | const elem_ty = ty.childType(); | ||
| 1036 | const elem_size = elem_ty.abiSize(target); | ||
| 1037 | var elem_i: usize = 0; | ||
| 1038 | var elem_value_buf: ElemValueBuffer = undefined; | ||
| 1039 | var buf_off: usize = 0; | ||
| 1040 | while (elem_i < len) : (elem_i += 1) { | ||
| 1041 | const elem_val = val.elemValueBuffer(elem_i, &elem_value_buf); | ||
| 1042 | writeToMemory(elem_val, elem_ty, target, buffer[buf_off..]); | ||
| 1043 | buf_off += elem_size; | ||
| 1044 | } | ||
| 1045 | }, | ||
| 1025 | else => @panic("TODO implement writeToMemory for more types"), | 1046 | else => @panic("TODO implement writeToMemory for more types"), |
| 1026 | } | 1047 | } |
| 1027 | } | 1048 | } |
test/behavior.zig+1-5| ... | @@ -47,6 +47,7 @@ test { | ... | @@ -47,6 +47,7 @@ test { |
| 47 | _ = @import("behavior/pointers.zig"); | 47 | _ = @import("behavior/pointers.zig"); |
| 48 | _ = @import("behavior/ptrcast.zig"); | 48 | _ = @import("behavior/ptrcast.zig"); |
| 49 | _ = @import("behavior/pub_enum.zig"); | 49 | _ = @import("behavior/pub_enum.zig"); |
| 50 | _ = @import("behavior/saturating_arithmetic.zig"); | ||
| 50 | _ = @import("behavior/sizeof_and_typeof.zig"); | 51 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| 51 | _ = @import("behavior/slice.zig"); | 52 | _ = @import("behavior/slice.zig"); |
| 52 | _ = @import("behavior/struct.zig"); | 53 | _ = @import("behavior/struct.zig"); |
| ... | @@ -150,11 +151,6 @@ test { | ... | @@ -150,11 +151,6 @@ test { |
| 150 | _ = @import("behavior/ptrcast_stage1.zig"); | 151 | _ = @import("behavior/ptrcast_stage1.zig"); |
| 151 | _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); | 152 | _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); |
| 152 | _ = @import("behavior/reflection.zig"); | 153 | _ = @import("behavior/reflection.zig"); |
| 153 | { | ||
| 154 | // Checklist for getting saturating_arithmetic.zig passing for stage2: | ||
| 155 | // * add __udivti3 to compiler-rt | ||
| 156 | _ = @import("behavior/saturating_arithmetic.zig"); | ||
| 157 | } | ||
| 158 | _ = @import("behavior/select.zig"); | 154 | _ = @import("behavior/select.zig"); |
| 159 | _ = @import("behavior/shuffle.zig"); | 155 | _ = @import("behavior/shuffle.zig"); |
| 160 | _ = @import("behavior/sizeof_and_typeof_stage1.zig"); | 156 | _ = @import("behavior/sizeof_and_typeof_stage1.zig"); |
test/behavior/bitcast.zig+22| ... | @@ -42,3 +42,25 @@ test "nested bitcast" { | ... | @@ -42,3 +42,25 @@ test "nested bitcast" { |
| 42 | try S.foo(42); | 42 | try S.foo(42); |
| 43 | comptime try S.foo(42); | 43 | comptime try S.foo(42); |
| 44 | } | 44 | } |
| 45 | |||
| 46 | test "@bitCast enum to its integer type" { | ||
| 47 | const SOCK = enum(c_int) { | ||
| 48 | A, | ||
| 49 | B, | ||
| 50 | |||
| 51 | fn testBitCastExternEnum() !void { | ||
| 52 | var SOCK_DGRAM = @This().B; | ||
| 53 | var sock_dgram = @bitCast(c_int, SOCK_DGRAM); | ||
| 54 | try expect(sock_dgram == 1); | ||
| 55 | } | ||
| 56 | }; | ||
| 57 | |||
| 58 | try SOCK.testBitCastExternEnum(); | ||
| 59 | comptime try SOCK.testBitCastExternEnum(); | ||
| 60 | } | ||
| 61 | |||
| 62 | // issue #3010: compiler segfault | ||
| 63 | test "bitcast literal [4]u8 param to u32" { | ||
| 64 | const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 }); | ||
| 65 | try expect(ip == maxInt(u32)); | ||
| 66 | } |
test/behavior/bitcast_stage1.zig-22| ... | @@ -5,22 +5,6 @@ const expectEqual = std.testing.expectEqual; | ... | @@ -5,22 +5,6 @@ const expectEqual = std.testing.expectEqual; |
| 5 | const maxInt = std.math.maxInt; | 5 | const maxInt = std.math.maxInt; |
| 6 | const native_endian = builtin.target.cpu.arch.endian(); | 6 | const native_endian = builtin.target.cpu.arch.endian(); |
| 7 | 7 | ||
| 8 | test "@bitCast enum to its integer type" { | ||
| 9 | const SOCK = enum(c_int) { | ||
| 10 | A, | ||
| 11 | B, | ||
| 12 | |||
| 13 | fn testBitCastExternEnum() !void { | ||
| 14 | var SOCK_DGRAM = @This().B; | ||
| 15 | var sock_dgram = @bitCast(c_int, SOCK_DGRAM); | ||
| 16 | try expect(sock_dgram == 1); | ||
| 17 | } | ||
| 18 | }; | ||
| 19 | |||
| 20 | try SOCK.testBitCastExternEnum(); | ||
| 21 | comptime try SOCK.testBitCastExternEnum(); | ||
| 22 | } | ||
| 23 | |||
| 24 | test "@bitCast packed structs at runtime and comptime" { | 8 | test "@bitCast packed structs at runtime and comptime" { |
| 25 | const Full = packed struct { | 9 | const Full = packed struct { |
| 26 | number: u16, | 10 | number: u16, |
| ... | @@ -111,12 +95,6 @@ test "implicit cast to error union by returning" { | ... | @@ -111,12 +95,6 @@ test "implicit cast to error union by returning" { |
| 111 | comptime try S.entry(); | 95 | comptime try S.entry(); |
| 112 | } | 96 | } |
| 113 | 97 | ||
| 114 | // issue #3010: compiler segfault | ||
| 115 | test "bitcast literal [4]u8 param to u32" { | ||
| 116 | const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 }); | ||
| 117 | try expect(ip == maxInt(u32)); | ||
| 118 | } | ||
| 119 | |||
| 120 | test "bitcast packed struct literal to byte" { | 98 | test "bitcast packed struct literal to byte" { |
| 121 | const Foo = packed struct { | 99 | const Foo = packed struct { |
| 122 | value: u8, | 100 | value: u8, |