authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-22 15:12:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-22 15:35:35-07:00
log069c83d58cebba88275ee76ba01fabcd8e964573
treeab7e52f307bd23869e2461189383522dc64f42de
parent86b92809635607ff357ce96902e2aaf83c3fd029

stage2: change `@bitCast` to always be by-value

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 }
8383
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 these161 // 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 }
554629
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");
631631
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}
278278
279fn 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`.
280fn reachableExpr(293fn 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
7186fn 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}
72007183
7201fn typeOf(7184fn 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 RLS318 // 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}
13871386
1388fn 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
1394fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {1387fn 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
46test "@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
63test "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;
5const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
6const native_endian = builtin.target.cpu.arch.endian();6const native_endian = builtin.target.cpu.arch.endian();
77
8test "@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
24test "@bitCast packed structs at runtime and comptime" {8test "@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}
11397
114// issue #3010: compiler segfault
115test "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
120test "bitcast packed struct literal to byte" {98test "bitcast packed struct literal to byte" {
121 const Foo = packed struct {99 const Foo = packed struct {
122 value: u8,100 value: u8,