authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-26 18:20:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-28 13:24:43-07:00
log82fc360613e7070ffe7124fb070b151a382bd31b
treeba114f2d8b46afc955d257a22553b75fd59d21a0
parenta67dec1c9f86b5c74c91cd4fd3e7fe06c8440586

stage2: avoid panicking for unimplemented compiler code

Prevents the compiler from crashing when using `@memset` on extern unions, for example.

2 files changed, 9 insertions(+), 4 deletions(-)

src/Sema.zig+3
...@@ -26954,10 +26954,12 @@ fn storePtrVal(...@@ -26954,10 +26954,12 @@ fn storePtrVal(
26954 reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer) catch |err| switch (err) {26954 reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer) catch |err| switch (err) {
26955 error.ReinterpretDeclRef => unreachable,26955 error.ReinterpretDeclRef => unreachable,
26956 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already26956 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already
26957 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(sema.mod)}),
26957 };26958 };
26958 operand_val.writeToMemory(operand_ty, sema.mod, buffer[reinterpret.byte_offset..]) catch |err| switch (err) {26959 operand_val.writeToMemory(operand_ty, sema.mod, buffer[reinterpret.byte_offset..]) catch |err| switch (err) {
26959 error.ReinterpretDeclRef => unreachable,26960 error.ReinterpretDeclRef => unreachable,
26960 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already26961 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already
26962 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(sema.mod)}),
26961 };26963 };
2696226964
26963 const arena = mut_kit.beginArena(sema.mod);26965 const arena = mut_kit.beginArena(sema.mod);
...@@ -27908,6 +27910,7 @@ fn bitCastVal(...@@ -27908,6 +27910,7 @@ fn bitCastVal(
27908 val.writeToMemory(old_ty, sema.mod, buffer) catch |err| switch (err) {27910 val.writeToMemory(old_ty, sema.mod, buffer) catch |err| switch (err) {
27909 error.ReinterpretDeclRef => return null,27911 error.ReinterpretDeclRef => return null,
27910 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already27912 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already
27913 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{old_ty.fmt(sema.mod)}),
27911 };27914 };
27912 return try Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena);27915 return try Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena);
27913}27916}
src/value.zig+6-4
...@@ -1281,6 +1281,7 @@ pub const Value = extern union {...@@ -1281,6 +1281,7 @@ pub const Value = extern union {
1281 pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{1281 pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{
1282 ReinterpretDeclRef,1282 ReinterpretDeclRef,
1283 IllDefinedMemoryLayout,1283 IllDefinedMemoryLayout,
1284 Unimplemented,
1284 }!void {1285 }!void {
1285 const target = mod.getTarget();1286 const target = mod.getTarget();
1286 const endian = target.cpu.arch.endian();1287 const endian = target.cpu.arch.endian();
...@@ -1370,19 +1371,19 @@ pub const Value = extern union {...@@ -1370,19 +1371,19 @@ pub const Value = extern union {
1370 },1371 },
1371 .Union => switch (ty.containerLayout()) {1372 .Union => switch (ty.containerLayout()) {
1372 .Auto => return error.IllDefinedMemoryLayout,1373 .Auto => return error.IllDefinedMemoryLayout,
1373 .Extern => @panic("TODO implement writeToMemory for extern unions"),1374 .Extern => return error.Unimplemented,
1374 .Packed => {1375 .Packed => {
1375 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;1376 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
1376 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);1377 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1377 },1378 },
1378 },1379 },
1379 .Pointer => {1380 .Pointer => {
1380 assert(!ty.isSlice()); // No well defined layout.1381 if (ty.isSlice()) return error.IllDefinedMemoryLayout;
1381 if (val.isDeclRef()) return error.ReinterpretDeclRef;1382 if (val.isDeclRef()) return error.ReinterpretDeclRef;
1382 return val.writeToMemory(Type.usize, mod, buffer);1383 return val.writeToMemory(Type.usize, mod, buffer);
1383 },1384 },
1384 .Optional => {1385 .Optional => {
1385 assert(ty.isPtrLikeOptional());1386 if (!ty.isPtrLikeOptional()) return error.IllDefinedMemoryLayout;
1386 var buf: Type.Payload.ElemType = undefined;1387 var buf: Type.Payload.ElemType = undefined;
1387 const child = ty.optionalChild(&buf);1388 const child = ty.optionalChild(&buf);
1388 const opt_val = val.optionalValue();1389 const opt_val = val.optionalValue();
...@@ -1392,7 +1393,7 @@ pub const Value = extern union {...@@ -1392,7 +1393,7 @@ pub const Value = extern union {
1392 return writeToMemory(Value.zero, Type.usize, mod, buffer);1393 return writeToMemory(Value.zero, Type.usize, mod, buffer);
1393 }1394 }
1394 },1395 },
1395 else => @panic("TODO implement writeToMemory for more types"),1396 else => return error.Unimplemented,
1396 }1397 }
1397 }1398 }
13981399
...@@ -5401,6 +5402,7 @@ pub const Value = extern union {...@@ -5401,6 +5402,7 @@ pub const Value = extern union {
5401 // code late in compilation. So, this error handling is too aggressive and5402 // code late in compilation. So, this error handling is too aggressive and
5402 // causes some false negatives, causing less-than-ideal code generation.5403 // causes some false negatives, causing less-than-ideal code generation.
5403 error.IllDefinedMemoryLayout => return null,5404 error.IllDefinedMemoryLayout => return null,
5405 error.Unimplemented => return null,
5404 };5406 };
5405 const first_byte = byte_buffer[0];5407 const first_byte = byte_buffer[0];
5406 for (byte_buffer[1..]) |byte| {5408 for (byte_buffer[1..]) |byte| {