authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-08 01:00:59-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-01-08 01:00:59-05:00
logc4ab8d9e12afbe07fc5b3cc4535a9fa2cfcad94d
tree87b00360b19a327864f09cfe12289650eb50650d
parent1cdc51ec1012bc2a6d1c115eaaeb24a2a93c26c5
parent3871d5e55a6d52bacadd80163540a171e014605f
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10532 from Hejsil/stage2-bit-shifting-passing

Stage2 bit_shifting.zig passing

7 files changed, 171 insertions(+), 42 deletions(-)

src/Module.zig+42-1
...@@ -831,6 +831,10 @@ pub const Struct = struct {...@@ -831,6 +831,10 @@ pub const Struct = struct {
831 have_field_types,831 have_field_types,
832 layout_wip,832 layout_wip,
833 have_layout,833 have_layout,
834 fully_resolved_wip,
835 // The types and all its fields have had their layout resolved. Even through pointer,
836 // which `have_layout` does not ensure.
837 fully_resolved,
834 },838 },
835 /// If true, definitely nonzero size at runtime. If false, resolving the fields839 /// If true, definitely nonzero size at runtime. If false, resolving the fields
836 /// is necessary to determine whether it has bits at runtime.840 /// is necessary to determine whether it has bits at runtime.
...@@ -889,6 +893,22 @@ pub const Struct = struct {...@@ -889,6 +893,22 @@ pub const Struct = struct {
889 .have_field_types,893 .have_field_types,
890 .layout_wip,894 .layout_wip,
891 .have_layout,895 .have_layout,
896 .fully_resolved_wip,
897 .fully_resolved,
898 => true,
899 };
900 }
901
902 pub fn haveLayout(s: Struct) bool {
903 return switch (s.status) {
904 .none,
905 .field_types_wip,
906 .have_field_types,
907 .layout_wip,
908 => false,
909 .have_layout,
910 .fully_resolved_wip,
911 .fully_resolved,
892 => true,912 => true,
893 };913 };
894 }914 }
...@@ -1003,6 +1023,10 @@ pub const Union = struct {...@@ -1003,6 +1023,10 @@ pub const Union = struct {
1003 have_field_types,1023 have_field_types,
1004 layout_wip,1024 layout_wip,
1005 have_layout,1025 have_layout,
1026 fully_resolved_wip,
1027 // The types and all its fields have had their layout resolved. Even through pointer,
1028 // which `have_layout` does not ensure.
1029 fully_resolved,
1006 },1030 },
10071031
1008 pub const Field = struct {1032 pub const Field = struct {
...@@ -1033,6 +1057,8 @@ pub const Union = struct {...@@ -1033,6 +1057,8 @@ pub const Union = struct {
1033 .have_field_types,1057 .have_field_types,
1034 .layout_wip,1058 .layout_wip,
1035 .have_layout,1059 .have_layout,
1060 .fully_resolved_wip,
1061 .fully_resolved,
1036 => true,1062 => true,
1037 };1063 };
1038 }1064 }
...@@ -1102,8 +1128,22 @@ pub const Union = struct {...@@ -1102,8 +1128,22 @@ pub const Union = struct {
1102 tag_size: u64,1128 tag_size: u64,
1103 };1129 };
11041130
1131 pub fn haveLayout(u: Union) bool {
1132 return switch (u.status) {
1133 .none,
1134 .field_types_wip,
1135 .have_field_types,
1136 .layout_wip,
1137 => false,
1138 .have_layout,
1139 .fully_resolved_wip,
1140 .fully_resolved,
1141 => true,
1142 };
1143 }
1144
1105 pub fn getLayout(u: Union, target: Target, have_tag: bool) Layout {1145 pub fn getLayout(u: Union, target: Target, have_tag: bool) Layout {
1106 assert(u.status == .have_layout);1146 assert(u.haveLayout());
1107 var most_aligned_field: u32 = undefined;1147 var most_aligned_field: u32 = undefined;
1108 var most_aligned_field_size: u64 = undefined;1148 var most_aligned_field_size: u64 = undefined;
1109 var biggest_field: u32 = undefined;1149 var biggest_field: u32 = undefined;
...@@ -4397,6 +4437,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem...@@ -4397,6 +4437,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem
4397 const arg = try sema.addConstant(param_type, opv);4437 const arg = try sema.addConstant(param_type, opv);
4398 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);4438 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
4399 total_param_index += 1;4439 total_param_index += 1;
4440 runtime_param_index += 1;
4400 continue;4441 continue;
4401 }4442 }
4402 const ty_ref = try sema.addType(param_type);4443 const ty_ref = try sema.addType(param_type);
src/Sema.zig+80-17
...@@ -4503,14 +4503,14 @@ fn analyzeCall(...@@ -4503,14 +4503,14 @@ fn analyzeCall(
4503 const arg_src = call_src; // TODO: better source location4503 const arg_src = call_src; // TODO: better source location
4504 if (i < fn_params_len) {4504 if (i < fn_params_len) {
4505 const param_ty = func_ty.fnParamType(i);4505 const param_ty = func_ty.fnParamType(i);
4506 try sema.resolveTypeForCodegen(block, arg_src, param_ty);4506 try sema.resolveTypeFully(block, arg_src, param_ty);
4507 args[i] = try sema.coerce(block, param_ty, uncasted_arg, arg_src);4507 args[i] = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
4508 } else {4508 } else {
4509 args[i] = uncasted_arg;4509 args[i] = uncasted_arg;
4510 }4510 }
4511 }4511 }
45124512
4513 try sema.resolveTypeForCodegen(block, call_src, func_ty_info.return_type);4513 try sema.resolveTypeFully(block, call_src, func_ty_info.return_type);
45144514
4515 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +4515 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
4516 args.len);4516 args.len);
...@@ -4580,7 +4580,7 @@ fn finishGenericCall(...@@ -4580,7 +4580,7 @@ fn finishGenericCall(
4580 const param_ty = new_fn_ty.fnParamType(runtime_i);4580 const param_ty = new_fn_ty.fnParamType(runtime_i);
4581 const arg_src = call_src; // TODO: better source location4581 const arg_src = call_src; // TODO: better source location
4582 const uncasted_arg = uncasted_args[total_i];4582 const uncasted_arg = uncasted_args[total_i];
4583 try sema.resolveTypeForCodegen(block, arg_src, param_ty);4583 try sema.resolveTypeFully(block, arg_src, param_ty);
4584 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);4584 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
4585 runtime_args[runtime_i] = casted_arg;4585 runtime_args[runtime_i] = casted_arg;
4586 runtime_i += 1;4586 runtime_i += 1;
...@@ -4588,7 +4588,7 @@ fn finishGenericCall(...@@ -4588,7 +4588,7 @@ fn finishGenericCall(
4588 total_i += 1;4588 total_i += 1;
4589 }4589 }
45904590
4591 try sema.resolveTypeForCodegen(block, call_src, new_fn_ty.fnReturnType());4591 try sema.resolveTypeFully(block, call_src, new_fn_ty.fnReturnType());
4592 }4592 }
4593 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +4593 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
4594 runtime_args_len);4594 runtime_args_len);
...@@ -7318,8 +7318,8 @@ fn zirShr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -7318,8 +7318,8 @@ fn zirShr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
7318 const lhs = sema.resolveInst(extra.lhs);7318 const lhs = sema.resolveInst(extra.lhs);
7319 const rhs = sema.resolveInst(extra.rhs);7319 const rhs = sema.resolveInst(extra.rhs);
73207320
7321 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {7321 if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
7322 if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {7322 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
7323 const lhs_ty = sema.typeOf(lhs);7323 const lhs_ty = sema.typeOf(lhs);
7324 if (lhs_val.isUndef() or rhs_val.isUndef()) {7324 if (lhs_val.isUndef() or rhs_val.isUndef()) {
7325 return sema.addConstUndef(lhs_ty);7325 return sema.addConstUndef(lhs_ty);
...@@ -7331,6 +7331,12 @@ fn zirShr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -7331,6 +7331,12 @@ fn zirShr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
7331 const val = try lhs_val.shr(rhs_val, sema.arena);7331 const val = try lhs_val.shr(rhs_val, sema.arena);
7332 return sema.addConstant(lhs_ty, val);7332 return sema.addConstant(lhs_ty, val);
7333 }7333 }
7334 // Even if lhs is not comptime known, we can still deduce certain things based
7335 // on rhs.
7336 // If rhs is 0, return lhs without doing any calculations.
7337 else if (rhs_val.compareWithZero(.eq)) {
7338 return lhs;
7339 }
7334 }7340 }
73357341
7336 try sema.requireRuntimeBlock(block, src);7342 try sema.requireRuntimeBlock(block, src);
...@@ -15222,7 +15228,7 @@ fn resolveStructLayout(...@@ -15222,7 +15228,7 @@ fn resolveStructLayout(
15222 .field_types_wip, .layout_wip => {15228 .field_types_wip, .layout_wip => {
15223 return sema.fail(block, src, "struct {} depends on itself", .{ty});15229 return sema.fail(block, src, "struct {} depends on itself", .{ty});
15224 },15230 },
15225 .have_layout => return,15231 .have_layout, .fully_resolved_wip, .fully_resolved => return,
15226 }15232 }
15227 struct_obj.status = .layout_wip;15233 struct_obj.status = .layout_wip;
15228 for (struct_obj.fields.values()) |field| {15234 for (struct_obj.fields.values()) |field| {
...@@ -15244,7 +15250,7 @@ fn resolveUnionLayout(...@@ -15244,7 +15250,7 @@ fn resolveUnionLayout(
15244 .field_types_wip, .layout_wip => {15250 .field_types_wip, .layout_wip => {
15245 return sema.fail(block, src, "union {} depends on itself", .{ty});15251 return sema.fail(block, src, "union {} depends on itself", .{ty});
15246 },15252 },
15247 .have_layout => return,15253 .have_layout, .fully_resolved_wip, .fully_resolved => return,
15248 }15254 }
15249 union_obj.status = .layout_wip;15255 union_obj.status = .layout_wip;
15250 for (union_obj.fields.values()) |field| {15256 for (union_obj.fields.values()) |field| {
...@@ -15253,7 +15259,7 @@ fn resolveUnionLayout(...@@ -15253,7 +15259,7 @@ fn resolveUnionLayout(
15253 union_obj.status = .have_layout;15259 union_obj.status = .have_layout;
15254}15260}
1525515261
15256fn resolveTypeForCodegen(15262fn resolveTypeFully(
15257 sema: *Sema,15263 sema: *Sema,
15258 block: *Block,15264 block: *Block,
15259 src: LazySrcLoc,15265 src: LazySrcLoc,
...@@ -15262,20 +15268,67 @@ fn resolveTypeForCodegen(...@@ -15262,20 +15268,67 @@ fn resolveTypeForCodegen(
15262 switch (ty.zigTypeTag()) {15268 switch (ty.zigTypeTag()) {
15263 .Pointer => {15269 .Pointer => {
15264 const child_ty = try sema.resolveTypeFields(block, src, ty.childType());15270 const child_ty = try sema.resolveTypeFields(block, src, ty.childType());
15265 return resolveTypeForCodegen(sema, block, src, child_ty);15271 return resolveTypeFully(sema, block, src, child_ty);
15266 },15272 },
15267 .Struct => return resolveStructLayout(sema, block, src, ty),15273 .Struct => return resolveStructFully(sema, block, src, ty),
15268 .Union => return resolveUnionLayout(sema, block, src, ty),15274 .Union => return resolveUnionFully(sema, block, src, ty),
15269 .Array => return resolveTypeForCodegen(sema, block, src, ty.childType()),15275 .Array => return resolveTypeFully(sema, block, src, ty.childType()),
15270 .Optional => {15276 .Optional => {
15271 var buf: Type.Payload.ElemType = undefined;15277 var buf: Type.Payload.ElemType = undefined;
15272 return resolveTypeForCodegen(sema, block, src, ty.optionalChild(&buf));15278 return resolveTypeFully(sema, block, src, ty.optionalChild(&buf));
15273 },15279 },
15274 .ErrorUnion => return resolveTypeForCodegen(sema, block, src, ty.errorUnionPayload()),15280 .ErrorUnion => return resolveTypeFully(sema, block, src, ty.errorUnionPayload()),
15275 else => {},15281 else => {},
15276 }15282 }
15277}15283}
1527815284
15285fn resolveStructFully(
15286 sema: *Sema,
15287 block: *Block,
15288 src: LazySrcLoc,
15289 ty: Type,
15290) CompileError!void {
15291 try resolveStructLayout(sema, block, src, ty);
15292
15293 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
15294 const struct_obj = resolved_ty.castTag(.@"struct").?.data;
15295 switch (struct_obj.status) {
15296 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
15297 .fully_resolved_wip, .fully_resolved => return,
15298 }
15299
15300 // After we have resolve struct layout we have to go over the fields again to
15301 // make sure pointer fields get their child types resolved as well
15302 struct_obj.status = .fully_resolved_wip;
15303 for (struct_obj.fields.values()) |field| {
15304 try sema.resolveTypeFully(block, src, field.ty);
15305 }
15306 struct_obj.status = .fully_resolved;
15307}
15308
15309fn resolveUnionFully(
15310 sema: *Sema,
15311 block: *Block,
15312 src: LazySrcLoc,
15313 ty: Type,
15314) CompileError!void {
15315 try resolveUnionLayout(sema, block, src, ty);
15316
15317 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
15318 const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
15319 switch (union_obj.status) {
15320 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
15321 .fully_resolved_wip, .fully_resolved => return,
15322 }
15323
15324 // Same goes for unions (see comment about structs)
15325 union_obj.status = .fully_resolved_wip;
15326 for (union_obj.fields.values()) |field| {
15327 try sema.resolveTypeFully(block, src, field.ty);
15328 }
15329 union_obj.status = .fully_resolved;
15330}
15331
15279fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type {15332fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type {
15280 switch (ty.tag()) {15333 switch (ty.tag()) {
15281 .@"struct" => {15334 .@"struct" => {
...@@ -15285,7 +15338,12 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp...@@ -15285,7 +15338,12 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp
15285 .field_types_wip => {15338 .field_types_wip => {
15286 return sema.fail(block, src, "struct {} depends on itself", .{ty});15339 return sema.fail(block, src, "struct {} depends on itself", .{ty});
15287 },15340 },
15288 .have_field_types, .have_layout, .layout_wip => return ty,15341 .have_field_types,
15342 .have_layout,
15343 .layout_wip,
15344 .fully_resolved_wip,
15345 .fully_resolved,
15346 => return ty,
15289 }15347 }
1529015348
15291 struct_obj.status = .field_types_wip;15349 struct_obj.status = .field_types_wip;
...@@ -15318,7 +15376,12 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp...@@ -15318,7 +15376,12 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp
15318 .field_types_wip => {15376 .field_types_wip => {
15319 return sema.fail(block, src, "union {} depends on itself", .{ty});15377 return sema.fail(block, src, "union {} depends on itself", .{ty});
15320 },15378 },
15321 .have_field_types, .have_layout, .layout_wip => return ty,15379 .have_field_types,
15380 .have_layout,
15381 .layout_wip,
15382 .fully_resolved_wip,
15383 .fully_resolved,
15384 => return ty,
15322 }15385 }
1532315386
15324 union_obj.status = .field_types_wip;15387 union_obj.status = .field_types_wip;
src/codegen/llvm.zig+35-19
...@@ -2647,7 +2647,7 @@ pub const FuncGen = struct {...@@ -2647,7 +2647,7 @@ pub const FuncGen = struct {
2647 switch (struct_ty.zigTypeTag()) {2647 switch (struct_ty.zigTypeTag()) {
2648 .Struct => {2648 .Struct => {
2649 var ptr_ty_buf: Type.Payload.Pointer = undefined;2649 var ptr_ty_buf: Type.Payload.Pointer = undefined;
2650 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf);2650 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;
2651 const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, "");2651 const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, "");
2652 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);2652 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);
2653 return self.load(field_ptr, field_ptr_ty);2653 return self.load(field_ptr, field_ptr_ty);
...@@ -4354,8 +4354,18 @@ pub const FuncGen = struct {...@@ -4354,8 +4354,18 @@ pub const FuncGen = struct {
4354 .Struct => {4354 .Struct => {
4355 const target = self.dg.module.getTarget();4355 const target = self.dg.module.getTarget();
4356 var ty_buf: Type.Payload.Pointer = undefined;4356 var ty_buf: Type.Payload.Pointer = undefined;
4357 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ty_buf);4357 if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| {
4358 return self.builder.buildStructGEP(struct_ptr, llvm_field_index, "");4358 return self.builder.buildStructGEP(struct_ptr, llvm_field_index, "");
4359 } else {
4360 // If we found no index then this means this is a zero sized field at the
4361 // end of the struct. Treat our struct pointer as an array of two and get
4362 // the index to the element at index `1` to get a pointer to the end of
4363 // the struct.
4364 const llvm_usize = try self.dg.llvmType(Type.usize);
4365 const llvm_index = llvm_usize.constInt(1, .False);
4366 const indices: [1]*const llvm.Value = .{llvm_index};
4367 return self.builder.buildInBoundsGEP(struct_ptr, &indices, indices.len, "");
4368 }
4359 },4369 },
4360 .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index),4370 .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index),
4361 else => unreachable,4371 else => unreachable,
...@@ -4750,32 +4760,37 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca...@@ -4750,32 +4760,37 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca
4750 };4760 };
4751}4761}
47524762
4753/// Take into account 0 bit fields.4763/// Take into account 0 bit fields. Returns null if an llvm field could not be found. This only
4764/// happends if you want the field index of a zero sized field at the end of the struct.
4754fn llvmFieldIndex(4765fn llvmFieldIndex(
4755 ty: Type,4766 ty: Type,
4756 field_index: u32,4767 field_index: u32,
4757 target: std.Target,4768 target: std.Target,
4758 ptr_pl_buf: *Type.Payload.Pointer,4769 ptr_pl_buf: *Type.Payload.Pointer,
4759) c_uint {4770) ?c_uint {
4760 const struct_obj = ty.castTag(.@"struct").?.data;4771 const struct_obj = ty.castTag(.@"struct").?.data;
4761 if (struct_obj.layout != .Packed) {4772 if (struct_obj.layout != .Packed) {
4762 var llvm_field_index: c_uint = 0;4773 var llvm_field_index: c_uint = 0;
4763 for (struct_obj.fields.values()) |field, i| {4774 for (struct_obj.fields.values()) |field, i| {
4764 if (!field.ty.hasCodeGenBits()) continue;4775 if (!field.ty.hasCodeGenBits())
47654776 continue;
4766 if (i == field_index) {4777 if (field_index > i) {
4767 ptr_pl_buf.* = .{4778 llvm_field_index += 1;
4768 .data = .{4779 continue;
4769 .pointee_type = field.ty,
4770 .@"align" = field.normalAlignment(target),
4771 .@"addrspace" = .generic,
4772 },
4773 };
4774 return llvm_field_index;
4775 }4780 }
4776 llvm_field_index += 1;4781
4782 ptr_pl_buf.* = .{
4783 .data = .{
4784 .pointee_type = field.ty,
4785 .@"align" = field.normalAlignment(target),
4786 .@"addrspace" = .generic,
4787 },
4788 };
4789 return llvm_field_index;
4790 } else {
4791 // We did not find an llvm field that corrispons to this zig field.
4792 return null;
4777 }4793 }
4778 unreachable;
4779 }4794 }
47804795
4781 // Our job here is to return the host integer field index.4796 // Our job here is to return the host integer field index.
...@@ -4784,7 +4799,8 @@ fn llvmFieldIndex(...@@ -4784,7 +4799,8 @@ fn llvmFieldIndex(
4784 var running_bits: u16 = 0;4799 var running_bits: u16 = 0;
4785 var llvm_field_index: c_uint = 0;4800 var llvm_field_index: c_uint = 0;
4786 for (struct_obj.fields.values()) |field, i| {4801 for (struct_obj.fields.values()) |field, i| {
4787 if (!field.ty.hasCodeGenBits()) continue;4802 if (!field.ty.hasCodeGenBits())
4803 continue;
47884804
4789 const field_align = field.packedAlignment();4805 const field_align = field.packedAlignment();
4790 if (field_align == 0) {4806 if (field_align == 0) {
src/type.zig+3-3
...@@ -1916,7 +1916,7 @@ pub const Type = extern union {...@@ -1916,7 +1916,7 @@ pub const Type = extern union {
1916 const fields = self.structFields();1916 const fields = self.structFields();
1917 const is_packed = if (self.castTag(.@"struct")) |payload| p: {1917 const is_packed = if (self.castTag(.@"struct")) |payload| p: {
1918 const struct_obj = payload.data;1918 const struct_obj = payload.data;
1919 assert(struct_obj.status == .have_layout);1919 assert(struct_obj.haveLayout());
1920 break :p struct_obj.layout == .Packed;1920 break :p struct_obj.layout == .Packed;
1921 } else false;1921 } else false;
19221922
...@@ -2220,7 +2220,7 @@ pub const Type = extern union {...@@ -2220,7 +2220,7 @@ pub const Type = extern union {
2220 if (field_count == 0) return 0;2220 if (field_count == 0) return 0;
22212221
2222 const struct_obj = ty.castTag(.@"struct").?.data;2222 const struct_obj = ty.castTag(.@"struct").?.data;
2223 assert(struct_obj.status == .have_layout);2223 assert(struct_obj.haveLayout());
22242224
2225 var total: u64 = 0;2225 var total: u64 = 0;
2226 for (struct_obj.fields.values()) |field| {2226 for (struct_obj.fields.values()) |field| {
...@@ -3771,7 +3771,7 @@ pub const Type = extern union {...@@ -3771,7 +3771,7 @@ pub const Type = extern union {
3771 switch (ty.tag()) {3771 switch (ty.tag()) {
3772 .@"struct" => {3772 .@"struct" => {
3773 const struct_obj = ty.castTag(.@"struct").?.data;3773 const struct_obj = ty.castTag(.@"struct").?.data;
3774 assert(struct_obj.status == .have_layout);3774 assert(struct_obj.haveLayout());
3775 const is_packed = struct_obj.layout == .Packed;3775 const is_packed = struct_obj.layout == .Packed;
3776 if (!is_packed) {3776 if (!is_packed) {
3777 var offset: u64 = 0;3777 var offset: u64 = 0;
src/value.zig+9-1
...@@ -2635,9 +2635,17 @@ pub const Value = extern union {...@@ -2635,9 +2635,17 @@ pub const Value = extern union {
2635 var lhs_space: Value.BigIntSpace = undefined;2635 var lhs_space: Value.BigIntSpace = undefined;
2636 const lhs_bigint = lhs.toBigInt(&lhs_space);2636 const lhs_bigint = lhs.toBigInt(&lhs_space);
2637 const shift = @intCast(usize, rhs.toUnsignedInt());2637 const shift = @intCast(usize, rhs.toUnsignedInt());
2638
2639 const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8));
2640 if (result_limbs == 0) {
2641 // The shift is enough to remove all the bits from the number, which means the
2642 // result is zero.
2643 return Value.zero;
2644 }
2645
2638 const limbs = try allocator.alloc(2646 const limbs = try allocator.alloc(
2639 std.math.big.Limb,2647 std.math.big.Limb,
2640 lhs_bigint.limbs.len - (shift / (@sizeOf(std.math.big.Limb) * 8)),2648 result_limbs,
2641 );2649 );
2642 var result_bigint = BigIntMutable{2650 var result_bigint = BigIntMutable{
2643 .limbs = limbs,2651 .limbs = limbs,
test/behavior.zig+1-1
...@@ -73,6 +73,7 @@ test {...@@ -73,6 +73,7 @@ test {
73 _ = @import("behavior/array_llvm.zig");73 _ = @import("behavior/array_llvm.zig");
74 _ = @import("behavior/atomics.zig");74 _ = @import("behavior/atomics.zig");
75 _ = @import("behavior/basic_llvm.zig");75 _ = @import("behavior/basic_llvm.zig");
76 _ = @import("behavior/bit_shifting.zig");
76 _ = @import("behavior/bugs/394.zig");77 _ = @import("behavior/bugs/394.zig");
77 _ = @import("behavior/bugs/656.zig");78 _ = @import("behavior/bugs/656.zig");
78 _ = @import("behavior/bugs/1277.zig");79 _ = @import("behavior/bugs/1277.zig");
...@@ -120,7 +121,6 @@ test {...@@ -120,7 +121,6 @@ test {
120 _ = @import("behavior/async_fn.zig");121 _ = @import("behavior/async_fn.zig");
121 }122 }
122 _ = @import("behavior/await_struct.zig");123 _ = @import("behavior/await_struct.zig");
123 _ = @import("behavior/bit_shifting.zig");
124 _ = @import("behavior/bitcast_stage1.zig");124 _ = @import("behavior/bitcast_stage1.zig");
125 _ = @import("behavior/bitreverse.zig");125 _ = @import("behavior/bitreverse.zig");
126 _ = @import("behavior/bugs/421.zig");126 _ = @import("behavior/bugs/421.zig");
test/behavior/bit_shifting.zig+1
...@@ -72,6 +72,7 @@ test "sharded table" {...@@ -72,6 +72,7 @@ test "sharded table" {
7272
73 try testShardedTable(u0, 0, 1);73 try testShardedTable(u0, 0, 1);
74}74}
75
75fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) !void {76fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) !void {
76 const Table = ShardedTable(Key, mask_bit_count, void);77 const Table = ShardedTable(Key, mask_bit_count, void);
7778