authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-02-18 22:05:09+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-19 13:54:52-05:00
logf10950526ea781ee2d15df74398527420cca13a1
treeb49b1a4e0690cc7c8d7cb047c644a8301661ab6b
parent02f5d2673f1bb21e7329acdd664fed565ecd4317

implement `writeToMemory`/`readFromMemory` for pointers


6 files changed, 74 insertions(+), 36 deletions(-)

src/Sema.zig+30-21
...@@ -2529,7 +2529,7 @@ fn coerceResultPtr(...@@ -2529,7 +2529,7 @@ fn coerceResultPtr(
2529 _ = try block.addBinOp(.store, new_ptr, null_inst);2529 _ = try block.addBinOp(.store, new_ptr, null_inst);
2530 return Air.Inst.Ref.void_value;2530 return Air.Inst.Ref.void_value;
2531 }2531 }
2532 return sema.bitCast(block, ptr_ty, new_ptr, src);2532 return sema.bitCast(block, ptr_ty, new_ptr, src, null);
2533 }2533 }
25342534
2535 const trash_inst = trash_block.instructions.pop();2535 const trash_inst = trash_block.instructions.pop();
...@@ -2545,7 +2545,7 @@ fn coerceResultPtr(...@@ -2545,7 +2545,7 @@ fn coerceResultPtr(
2545 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {2545 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
2546 new_ptr = try sema.addConstant(ptr_operand_ty, ptr_val);2546 new_ptr = try sema.addConstant(ptr_operand_ty, ptr_val);
2547 } else {2547 } else {
2548 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src);2548 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);
2549 }2549 }
2550 },2550 },
2551 .wrap_optional => {2551 .wrap_optional => {
...@@ -9655,7 +9655,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9655,7 +9655,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9655 .Vector,9655 .Vector,
9656 => {},9656 => {},
9657 }9657 }
9658 return sema.bitCast(block, dest_ty, operand, operand_src);9658 return sema.bitCast(block, dest_ty, operand, inst_data.src(), operand_src);
9659}9659}
96609660
9661fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9661fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -9888,7 +9888,7 @@ fn zirSwitchCapture(...@@ -9888,7 +9888,7 @@ fn zirSwitchCapture(
98889888
9889 switch (operand_ty.zigTypeTag()) {9889 switch (operand_ty.zigTypeTag()) {
9890 .ErrorSet => if (block.switch_else_err_ty) |some| {9890 .ErrorSet => if (block.switch_else_err_ty) |some| {
9891 return sema.bitCast(block, some, operand, operand_src);9891 return sema.bitCast(block, some, operand, operand_src, null);
9892 } else {9892 } else {
9893 try block.addUnreachable(false);9893 try block.addUnreachable(false);
9894 return Air.Inst.Ref.unreachable_value;9894 return Air.Inst.Ref.unreachable_value;
...@@ -9988,14 +9988,14 @@ fn zirSwitchCapture(...@@ -9988,14 +9988,14 @@ fn zirSwitchCapture(
9988 Module.ErrorSet.sortNames(&names);9988 Module.ErrorSet.sortNames(&names);
9989 const else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);9989 const else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
99909990
9991 return sema.bitCast(block, else_error_ty, operand, operand_src);9991 return sema.bitCast(block, else_error_ty, operand, operand_src, null);
9992 } else {9992 } else {
9993 const item_ref = try sema.resolveInst(items[0]);9993 const item_ref = try sema.resolveInst(items[0]);
9994 // Previous switch validation ensured this will succeed9994 // Previous switch validation ensured this will succeed
9995 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;9995 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
99969996
9997 const item_ty = try Type.Tag.error_set_single.create(sema.arena, item_val.getError().?);9997 const item_ty = try Type.Tag.error_set_single.create(sema.arena, item_val.getError().?);
9998 return sema.bitCast(block, item_ty, operand, operand_src);9998 return sema.bitCast(block, item_ty, operand, operand_src, null);
9999 }9999 }
10000 },10000 },
10001 else => {10001 else => {
...@@ -19953,7 +19953,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -19953,7 +19953,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
19953 } else is_aligned;19953 } else is_aligned;
19954 try sema.addSafetyCheck(block, ok, .incorrect_alignment);19954 try sema.addSafetyCheck(block, ok, .incorrect_alignment);
19955 }19955 }
19956 return sema.bitCast(block, dest_ty, ptr, ptr_src);19956 return sema.bitCast(block, dest_ty, ptr, ptr_src, null);
19957}19957}
1995819958
19959fn zirBitCount(19959fn zirBitCount(
...@@ -24141,8 +24141,9 @@ fn unionFieldVal(...@@ -24141,8 +24141,9 @@ fn unionFieldVal(
24141 return sema.addConstant(field.ty, tag_and_val.val);24141 return sema.addConstant(field.ty, tag_and_val.val);
24142 } else {24142 } else {
24143 const old_ty = union_ty.unionFieldType(tag_and_val.tag, sema.mod);24143 const old_ty = union_ty.unionFieldType(tag_and_val.tag, sema.mod);
24144 const new_val = try sema.bitCastVal(block, src, tag_and_val.val, old_ty, field.ty, 0);24144 if (try sema.bitCastVal(block, src, tag_and_val.val, old_ty, field.ty, 0)) |new_val| {
24145 return sema.addConstant(field.ty, new_val);24145 return sema.addConstant(field.ty, new_val);
24146 }
24146 }24147 }
24147 },24148 },
24148 }24149 }
...@@ -26514,8 +26515,12 @@ fn storePtrVal(...@@ -26514,8 +26515,12 @@ fn storePtrVal(
26514 const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(target));26515 const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(target));
26515 const buffer = try sema.gpa.alloc(u8, abi_size);26516 const buffer = try sema.gpa.alloc(u8, abi_size);
26516 defer sema.gpa.free(buffer);26517 defer sema.gpa.free(buffer);
26517 reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer);26518 reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer) catch |err| switch (err) {
26518 operand_val.writeToMemory(operand_ty, sema.mod, buffer[reinterpret.byte_offset..]);26519 error.ReinterpretDeclRef => unreachable,
26520 };
26521 operand_val.writeToMemory(operand_ty, sema.mod, buffer[reinterpret.byte_offset..]) catch |err| switch (err) {
26522 error.ReinterpretDeclRef => unreachable,
26523 };
2651926524
26520 const arena = mut_kit.beginArena(sema.mod);26525 const arena = mut_kit.beginArena(sema.mod);
26521 defer mut_kit.finishArena(sema.mod);26526 defer mut_kit.finishArena(sema.mod);
...@@ -27398,6 +27403,7 @@ fn bitCast(...@@ -27398,6 +27403,7 @@ fn bitCast(
27398 dest_ty_unresolved: Type,27403 dest_ty_unresolved: Type,
27399 inst: Air.Inst.Ref,27404 inst: Air.Inst.Ref,
27400 inst_src: LazySrcLoc,27405 inst_src: LazySrcLoc,
27406 operand_src: ?LazySrcLoc,
27401) CompileError!Air.Inst.Ref {27407) CompileError!Air.Inst.Ref {
27402 const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);27408 const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);
27403 try sema.resolveTypeLayout(dest_ty);27409 try sema.resolveTypeLayout(dest_ty);
...@@ -27419,10 +27425,11 @@ fn bitCast(...@@ -27419,10 +27425,11 @@ fn bitCast(
27419 }27425 }
2742027426
27421 if (try sema.resolveMaybeUndefVal(inst)) |val| {27427 if (try sema.resolveMaybeUndefVal(inst)) |val| {
27422 const result_val = try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty, 0);27428 if (try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty, 0)) |result_val| {
27423 return sema.addConstant(dest_ty, result_val);27429 return sema.addConstant(dest_ty, result_val);
27430 }
27424 }27431 }
27425 try sema.requireRuntimeBlock(block, inst_src, null);27432 try sema.requireRuntimeBlock(block, inst_src, operand_src);
27426 return block.addBitCast(dest_ty, inst);27433 return block.addBitCast(dest_ty, inst);
27427}27434}
2742827435
...@@ -27434,7 +27441,7 @@ fn bitCastVal(...@@ -27434,7 +27441,7 @@ fn bitCastVal(
27434 old_ty: Type,27441 old_ty: Type,
27435 new_ty: Type,27442 new_ty: Type,
27436 buffer_offset: usize,27443 buffer_offset: usize,
27437) !Value {27444) !?Value {
27438 const target = sema.mod.getTarget();27445 const target = sema.mod.getTarget();
27439 if (old_ty.eql(new_ty, sema.mod)) return val;27446 if (old_ty.eql(new_ty, sema.mod)) return val;
2744027447
...@@ -27443,8 +27450,10 @@ fn bitCastVal(...@@ -27443,8 +27450,10 @@ fn bitCastVal(
27443 const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target));27450 const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target));
27444 const buffer = try sema.gpa.alloc(u8, abi_size);27451 const buffer = try sema.gpa.alloc(u8, abi_size);
27445 defer sema.gpa.free(buffer);27452 defer sema.gpa.free(buffer);
27446 val.writeToMemory(old_ty, sema.mod, buffer);27453 val.writeToMemory(old_ty, sema.mod, buffer) catch |err| switch (err) {
27447 return Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena);27454 error.ReinterpretDeclRef => return null,
27455 };
27456 return try Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena);
27448}27457}
2744927458
27450fn coerceArrayPtrToSlice(27459fn coerceArrayPtrToSlice(
...@@ -27551,7 +27560,7 @@ fn coerceCompatiblePtrs(...@@ -27551,7 +27560,7 @@ fn coerceCompatiblePtrs(
27551 } else is_non_zero;27560 } else is_non_zero;
27552 try sema.addSafetyCheck(block, ok, .cast_to_null);27561 try sema.addSafetyCheck(block, ok, .cast_to_null);
27553 }27562 }
27554 return sema.bitCast(block, dest_ty, inst, inst_src);27563 return sema.bitCast(block, dest_ty, inst, inst_src, null);
27555}27564}
2755627565
27557fn coerceEnumToUnion(27566fn coerceEnumToUnion(
...@@ -28291,7 +28300,7 @@ fn analyzeRef(...@@ -28291,7 +28300,7 @@ fn analyzeRef(
28291 try sema.storePtr(block, src, alloc, operand);28300 try sema.storePtr(block, src, alloc, operand);
2829228301
28293 // TODO: Replace with sema.coerce when that supports adding pointer constness.28302 // TODO: Replace with sema.coerce when that supports adding pointer constness.
28294 return sema.bitCast(block, ptr_type, alloc, src);28303 return sema.bitCast(block, ptr_type, alloc, src, null);
28295}28304}
2829628305
28297fn analyzeLoad(28306fn analyzeLoad(
...@@ -32327,11 +32336,11 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value...@@ -32327,11 +32336,11 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
3232732336
32328 // Try the smaller bit-cast first, since that's more efficient than using the larger `parent`32337 // Try the smaller bit-cast first, since that's more efficient than using the larger `parent`
32329 if (deref.pointee) |tv| if (load_sz <= try sema.typeAbiSize(tv.ty))32338 if (deref.pointee) |tv| if (load_sz <= try sema.typeAbiSize(tv.ty))
32330 return DerefResult{ .val = try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0) };32339 return DerefResult{ .val = (try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0)) orelse return .runtime_load };
3233132340
32332 // If that fails, try to bit-cast from the largest parent value with a well-defined layout32341 // If that fails, try to bit-cast from the largest parent value with a well-defined layout
32333 if (deref.parent) |parent| if (load_sz + parent.byte_offset <= try sema.typeAbiSize(parent.tv.ty))32342 if (deref.parent) |parent| if (load_sz + parent.byte_offset <= try sema.typeAbiSize(parent.tv.ty))
32334 return DerefResult{ .val = try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset) };32343 return DerefResult{ .val = (try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset)) orelse return .runtime_load };
3233532344
32336 if (deref.ty_without_well_defined_layout) |bad_ty| {32345 if (deref.ty_without_well_defined_layout) |bad_ty| {
32337 // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem32346 // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem
src/arch/wasm/CodeGen.zig+2-2
...@@ -2896,7 +2896,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -2896,7 +2896,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
2896 const struct_obj = ty.castTag(.@"struct").?.data;2896 const struct_obj = ty.castTag(.@"struct").?.data;
2897 assert(struct_obj.layout == .Packed);2897 assert(struct_obj.layout == .Packed);
2898 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer2898 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
2899 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0);2899 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
2900 var payload: Value.Payload.U64 = .{2900 var payload: Value.Payload.U64 = .{
2901 .base = .{ .tag = .int_u64 },2901 .base = .{ .tag = .int_u64 },
2902 .data = std.mem.readIntLittle(u64, &buf),2902 .data = std.mem.readIntLittle(u64, &buf),
...@@ -2907,7 +2907,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -2907,7 +2907,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
2907 .Vector => {2907 .Vector => {
2908 assert(determineSimdStoreStrategy(ty, target) == .direct);2908 assert(determineSimdStoreStrategy(ty, target) == .direct);
2909 var buf: [16]u8 = undefined;2909 var buf: [16]u8 = undefined;
2910 val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf);2910 val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable;
2911 return func.storeSimdImmd(buf);2911 return func.storeSimdImmd(buf);
2912 },2912 },
2913 else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),2913 else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),
src/codegen.zig+1-1
...@@ -527,7 +527,7 @@ pub fn generateSymbol(...@@ -527,7 +527,7 @@ pub fn generateSymbol(
527 .fail => |em| return Result{ .fail = em },527 .fail => |em| return Result{ .fail = em },
528 }528 }
529 } else {529 } else {
530 field_val.writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits);530 field_val.writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable;
531 }531 }
532 bits += @intCast(u16, field_ty.bitSize(target));532 bits += @intCast(u16, field_ty.bitSize(target));
533 }533 }
src/value.zig+39-10
...@@ -1249,11 +1249,22 @@ pub const Value = extern union {...@@ -1249,11 +1249,22 @@ pub const Value = extern union {
1249 };1249 };
1250 }1250 }
12511251
1252 fn isDeclRef(val: Value) bool {
1253 var check = val;
1254 while (true) switch (check.tag()) {
1255 .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return true,
1256 .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,
1257 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,
1258 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,
1259 else => return false,
1260 };
1261 }
1262
1252 /// Write a Value's contents to `buffer`.1263 /// Write a Value's contents to `buffer`.
1253 ///1264 ///
1254 /// Asserts that buffer.len >= ty.abiSize(). The buffer is allowed to extend past1265 /// Asserts that buffer.len >= ty.abiSize(). The buffer is allowed to extend past
1255 /// the end of the value in memory.1266 /// the end of the value in memory.
1256 pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) void {1267 pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{ReinterpretDeclRef}!void {
1257 const target = mod.getTarget();1268 const target = mod.getTarget();
1258 const endian = target.cpu.arch.endian();1269 const endian = target.cpu.arch.endian();
1259 if (val.isUndef()) {1270 if (val.isUndef()) {
...@@ -1309,7 +1320,7 @@ pub const Value = extern union {...@@ -1309,7 +1320,7 @@ pub const Value = extern union {
1309 var buf_off: usize = 0;1320 var buf_off: usize = 0;
1310 while (elem_i < len) : (elem_i += 1) {1321 while (elem_i < len) : (elem_i += 1) {
1311 const elem_val = val.elemValueBuffer(mod, elem_i, &elem_value_buf);1322 const elem_val = val.elemValueBuffer(mod, elem_i, &elem_value_buf);
1312 elem_val.writeToMemory(elem_ty, mod, buffer[buf_off..]);1323 try elem_val.writeToMemory(elem_ty, mod, buffer[buf_off..]);
1313 buf_off += elem_size;1324 buf_off += elem_size;
1314 }1325 }
1315 },1326 },
...@@ -1317,7 +1328,7 @@ pub const Value = extern union {...@@ -1317,7 +1328,7 @@ pub const Value = extern union {
1317 // We use byte_count instead of abi_size here, so that any padding bytes1328 // We use byte_count instead of abi_size here, so that any padding bytes
1318 // follow the data bytes, on both big- and little-endian systems.1329 // follow the data bytes, on both big- and little-endian systems.
1319 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;1330 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
1320 writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);1331 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1321 },1332 },
1322 .Struct => switch (ty.containerLayout()) {1333 .Struct => switch (ty.containerLayout()) {
1323 .Auto => unreachable, // Sema is supposed to have emitted a compile error already1334 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
...@@ -1326,12 +1337,12 @@ pub const Value = extern union {...@@ -1326,12 +1337,12 @@ pub const Value = extern union {
1326 const field_vals = val.castTag(.aggregate).?.data;1337 const field_vals = val.castTag(.aggregate).?.data;
1327 for (fields, 0..) |field, i| {1338 for (fields, 0..) |field, i| {
1328 const off = @intCast(usize, ty.structFieldOffset(i, target));1339 const off = @intCast(usize, ty.structFieldOffset(i, target));
1329 writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);1340 try writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);
1330 }1341 }
1331 },1342 },
1332 .Packed => {1343 .Packed => {
1333 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;1344 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
1334 writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);1345 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1335 },1346 },
1336 },1347 },
1337 .ErrorSet => {1348 .ErrorSet => {
...@@ -1345,9 +1356,14 @@ pub const Value = extern union {...@@ -1345,9 +1356,14 @@ pub const Value = extern union {
1345 .Extern => @panic("TODO implement writeToMemory for extern unions"),1356 .Extern => @panic("TODO implement writeToMemory for extern unions"),
1346 .Packed => {1357 .Packed => {
1347 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;1358 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
1348 writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);1359 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1349 },1360 },
1350 },1361 },
1362 .Pointer => {
1363 assert(!ty.isSlice()); // No well defined layout.
1364 if (val.isDeclRef()) return error.ReinterpretDeclRef;
1365 return val.writeToMemory(Type.usize, mod, buffer);
1366 },
1351 else => @panic("TODO implement writeToMemory for more types"),1367 else => @panic("TODO implement writeToMemory for more types"),
1352 }1368 }
1353 }1369 }
...@@ -1356,7 +1372,7 @@ pub const Value = extern union {...@@ -1356,7 +1372,7 @@ pub const Value = extern union {
1356 ///1372 ///
1357 /// Both the start and the end of the provided buffer must be tight, since1373 /// Both the start and the end of the provided buffer must be tight, since
1358 /// big-endian packed memory layouts start at the end of the buffer.1374 /// big-endian packed memory layouts start at the end of the buffer.
1359 pub fn writeToPackedMemory(val: Value, ty: Type, mod: *Module, buffer: []u8, bit_offset: usize) void {1375 pub fn writeToPackedMemory(val: Value, ty: Type, mod: *Module, buffer: []u8, bit_offset: usize) error{ReinterpretDeclRef}!void {
1360 const target = mod.getTarget();1376 const target = mod.getTarget();
1361 const endian = target.cpu.arch.endian();1377 const endian = target.cpu.arch.endian();
1362 if (val.isUndef()) {1378 if (val.isUndef()) {
...@@ -1420,7 +1436,7 @@ pub const Value = extern union {...@@ -1420,7 +1436,7 @@ pub const Value = extern union {
1420 // On big-endian systems, LLVM reverses the element order of vectors by default1436 // On big-endian systems, LLVM reverses the element order of vectors by default
1421 const tgt_elem_i = if (endian == .Big) len - elem_i - 1 else elem_i;1437 const tgt_elem_i = if (endian == .Big) len - elem_i - 1 else elem_i;
1422 const elem_val = val.elemValueBuffer(mod, tgt_elem_i, &elem_value_buf);1438 const elem_val = val.elemValueBuffer(mod, tgt_elem_i, &elem_value_buf);
1423 elem_val.writeToPackedMemory(elem_ty, mod, buffer, bit_offset + bits);1439 try elem_val.writeToPackedMemory(elem_ty, mod, buffer, bit_offset + bits);
1424 bits += elem_bit_size;1440 bits += elem_bit_size;
1425 }1441 }
1426 },1442 },
...@@ -1433,7 +1449,7 @@ pub const Value = extern union {...@@ -1433,7 +1449,7 @@ pub const Value = extern union {
1433 const field_vals = val.castTag(.aggregate).?.data;1449 const field_vals = val.castTag(.aggregate).?.data;
1434 for (fields, 0..) |field, i| {1450 for (fields, 0..) |field, i| {
1435 const field_bits = @intCast(u16, field.ty.bitSize(target));1451 const field_bits = @intCast(u16, field.ty.bitSize(target));
1436 field_vals[i].writeToPackedMemory(field.ty, mod, buffer, bit_offset + bits);1452 try field_vals[i].writeToPackedMemory(field.ty, mod, buffer, bit_offset + bits);
1437 bits += field_bits;1453 bits += field_bits;
1438 }1454 }
1439 },1455 },
...@@ -1446,9 +1462,14 @@ pub const Value = extern union {...@@ -1446,9 +1462,14 @@ pub const Value = extern union {
1446 const field_type = ty.unionFields().values()[field_index.?].ty;1462 const field_type = ty.unionFields().values()[field_index.?].ty;
1447 const field_val = val.fieldValue(field_type, field_index.?);1463 const field_val = val.fieldValue(field_type, field_index.?);
14481464
1449 field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);1465 return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);
1450 },1466 },
1451 },1467 },
1468 .Pointer => {
1469 assert(!ty.isSlice()); // No well defined layout.
1470 if (val.isDeclRef()) return error.ReinterpretDeclRef;
1471 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);
1472 },
1452 else => @panic("TODO implement writeToPackedMemory for more types"),1473 else => @panic("TODO implement writeToPackedMemory for more types"),
1453 }1474 }
1454 }1475 }
...@@ -1553,6 +1574,10 @@ pub const Value = extern union {...@@ -1553,6 +1574,10 @@ pub const Value = extern union {
1553 };1574 };
1554 return Value.initPayload(&payload.base);1575 return Value.initPayload(&payload.base);
1555 },1576 },
1577 .Pointer => {
1578 assert(!ty.isSlice()); // No well defined layout.
1579 return readFromMemory(Type.usize, mod, buffer, arena);
1580 },
1556 else => @panic("TODO implement readFromMemory for more types"),1581 else => @panic("TODO implement readFromMemory for more types"),
1557 }1582 }
1558 }1583 }
...@@ -1640,6 +1665,10 @@ pub const Value = extern union {...@@ -1640,6 +1665,10 @@ pub const Value = extern union {
1640 return Tag.aggregate.create(arena, field_vals);1665 return Tag.aggregate.create(arena, field_vals);
1641 },1666 },
1642 },1667 },
1668 .Pointer => {
1669 assert(!ty.isSlice()); // No well defined layout.
1670 return readFromPackedMemory(Type.usize, mod, buffer, bit_offset, arena);
1671 },
1643 else => @panic("TODO implement readFromPackedMemory for more types"),1672 else => @panic("TODO implement readFromPackedMemory for more types"),
1644 }1673 }
1645 }1674 }
test/cases/compile_errors/bitCast_same_size_but_bit_count_mismatch.zig+1-1
...@@ -7,4 +7,4 @@ export fn entry(byte: u8) void {...@@ -7,4 +7,4 @@ export fn entry(byte: u8) void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:29: error: @bitCast size mismatch: destination type 'u7' has 7 bits but source type 'u8' has 8 bits10// :2:16: error: @bitCast size mismatch: destination type 'u7' has 7 bits but source type 'u8' has 8 bits
test/cases/compile_errors/bitCast_with_different_sizes_inside_an_expression.zig+1-1
...@@ -7,4 +7,4 @@ export fn entry() void {...@@ -7,4 +7,4 @@ export fn entry() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:29: error: @bitCast size mismatch: destination type 'u8' has 8 bits but source type 'f32' has 32 bits10// :2:16: error: @bitCast size mismatch: destination type 'u8' has 8 bits but source type 'f32' has 32 bits