authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-07-24 19:48:55+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-07-24 20:05:41+02:00
log30376a82b2c1b13047ff3b48391fcda44183e129
treec8c30217017f3003303b077230fd02a798335151
parent5d98abd5703607884844e8b8165dcc2238389c57
signaturelock-open Commit is signed but in an unrecognized format.

Re-enable switch test cases and fix regressions


2 files changed, 98 insertions(+), 72 deletions(-)

src/codegen/wasm.zig+38-10
...@@ -1084,6 +1084,42 @@ pub const Context = struct {...@@ -1084,6 +1084,42 @@ pub const Context = struct {
1084 }1084 }
1085 }1085 }
10861086
1087 /// Returns a `Value` as a signed 32 bit value.
1088 /// It's illegale to provide a value with a type that cannot be represented
1089 /// as an integer value.
1090 fn valueAsI32(self: Context, val: Value, ty: Type) i32 {
1091 switch (ty.zigTypeTag()) {
1092 .Enum => {
1093 if (val.castTag(.enum_field_index)) |field_index| {
1094 switch (ty.tag()) {
1095 .enum_simple => return @bitCast(i32, field_index.data),
1096 .enum_full, .enum_nonexhaustive => {
1097 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;
1098 if (enum_full.values.count() != 0) {
1099 const tag_val = enum_full.values.keys()[field_index.data];
1100 return self.valueAsI32(tag_val, enum_full.tag_ty);
1101 } else return @bitCast(i32, field_index.data);
1102 },
1103 else => unreachable,
1104 }
1105 } else {
1106 var int_tag_buffer: Type.Payload.Bits = undefined;
1107 const int_tag_ty = ty.intTagType(&int_tag_buffer);
1108 return self.valueAsI32(val, int_tag_ty);
1109 }
1110 },
1111 .Int => switch (ty.intInfo(self.target).signedness) {
1112 .signed => return @truncate(i32, val.toSignedInt()),
1113 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt())),
1114 },
1115 .ErrorSet => {
1116 const error_index = self.global_error_set.get(val.getError().?).?;
1117 return @bitCast(i32, error_index);
1118 },
1119 else => unreachable, // Programmer called this function for an illegal type
1120 }
1121 }
1122
1087 fn airBlock(self: *Context, inst: Air.Inst.Index) InnerError!WValue {1123 fn airBlock(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
1088 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1124 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1089 const block_ty = try self.genBlockType(self.air.getRefType(ty_pl.ty));1125 const block_ty = try self.genBlockType(self.air.getRefType(ty_pl.ty));
...@@ -1307,15 +1343,7 @@ pub const Context = struct {...@@ -1307,15 +1343,7 @@ pub const Context = struct {
13071343
1308 for (items) |ref, i| {1344 for (items) |ref, i| {
1309 const item_val = self.air.value(ref).?;1345 const item_val = self.air.value(ref).?;
1310 const int_val: i32 = blk: {1346 const int_val = self.valueAsI32(item_val, target_ty);
1311 if (target_ty.intInfo(self.target).signedness == .signed) {
1312 // safe to truncate the values as we only use them when
1313 // the target's bits is 32 or lower.
1314 break :blk @truncate(i32, item_val.toSignedInt());
1315 }
1316
1317 break :blk @bitCast(i32, @truncate(u32, item_val.toUnsignedInt()));
1318 };
1319 if (int_val < lowest) {1347 if (int_val < lowest) {
1320 lowest = int_val;1348 lowest = int_val;
1321 }1349 }
...@@ -1334,7 +1362,7 @@ pub const Context = struct {...@@ -1334,7 +1362,7 @@ pub const Context = struct {
1334 // When the target is an integer size larger than u32, we have no way to use the value1362 // When the target is an integer size larger than u32, we have no way to use the value
1335 // as an index, therefore we also use an if/else-chain for those cases.1363 // as an index, therefore we also use an if/else-chain for those cases.
1336 // TODO: Benchmark this to find a proper value, LLVM seems to draw the line at '40~45'.1364 // TODO: Benchmark this to find a proper value, LLVM seems to draw the line at '40~45'.
1337 const is_sparse = target_ty.intInfo(self.target).bits > 32 or highest - lowest > 50;1365 const is_sparse = highest - lowest > 50 or target_ty.bitSize(self.target) > 32;
13381366
1339 const else_body = self.air.extra[extra_index..][0..switch_br.data.else_body_len];1367 const else_body = self.air.extra[extra_index..][0..switch_br.data.else_body_len];
1340 const has_else_body = else_body.len != 0;1368 const has_else_body = else_body.len != 0;
test/stage2/wasm.zig+60-62
...@@ -479,68 +479,66 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -479,68 +479,66 @@ pub fn addCases(ctx: *TestContext) !void {
479 , "30\n");479 , "30\n");
480 }480 }
481481
482 // This test case is disabled until the codegen for switch is reworked482 {
483 // to take advantage of br_table rather than a series of br_if opcodes.483 var case = ctx.exe("wasm switch", wasi);
484 //{484
485 // var case = ctx.exe("wasm switch", wasi);485 case.addCompareOutput(
486486 \\pub export fn _start() u32 {
487 // case.addCompareOutput(487 \\ var val: u32 = 1;
488 // \\pub export fn _start() u32 {488 \\ var a: u32 = switch (val) {
489 // \\ var val: u32 = 1;489 \\ 0, 1 => 2,
490 // \\ var a: u32 = switch (val) {490 \\ 2 => 3,
491 // \\ 0, 1 => 2,491 \\ 3 => 4,
492 // \\ 2 => 3,492 \\ else => 5,
493 // \\ 3 => 4,493 \\ };
494 // \\ else => 5,494 \\
495 // \\ };495 \\ return a;
496 // \\496 \\}
497 // \\ return a;497 , "2\n");
498 // \\}498
499 // , "2\n");499 case.addCompareOutput(
500500 \\pub export fn _start() u32 {
501 // case.addCompareOutput(501 \\ var val: u32 = 2;
502 // \\pub export fn _start() u32 {502 \\ var a: u32 = switch (val) {
503 // \\ var val: u32 = 2;503 \\ 0, 1 => 2,
504 // \\ var a: u32 = switch (val) {504 \\ 2 => 3,
505 // \\ 0, 1 => 2,505 \\ 3 => 4,
506 // \\ 2 => 3,506 \\ else => 5,
507 // \\ 3 => 4,507 \\ };
508 // \\ else => 5,508 \\
509 // \\ };509 \\ return a;
510 // \\510 \\}
511 // \\ return a;511 , "3\n");
512 // \\}512
513 // , "3\n");513 case.addCompareOutput(
514514 \\pub export fn _start() u32 {
515 // case.addCompareOutput(515 \\ var val: u32 = 10;
516 // \\pub export fn _start() u32 {516 \\ var a: u32 = switch (val) {
517 // \\ var val: u32 = 10;517 \\ 0, 1 => 2,
518 // \\ var a: u32 = switch (val) {518 \\ 2 => 3,
519 // \\ 0, 1 => 2,519 \\ 3 => 4,
520 // \\ 2 => 3,520 \\ else => 5,
521 // \\ 3 => 4,521 \\ };
522 // \\ else => 5,522 \\
523 // \\ };523 \\ return a;
524 // \\524 \\}
525 // \\ return a;525 , "5\n");
526 // \\}526
527 // , "5\n");527 case.addCompareOutput(
528528 \\const MyEnum = enum { One, Two, Three };
529 // case.addCompareOutput(529 \\
530 // \\const MyEnum = enum { One, Two, Three };530 \\pub export fn _start() u32 {
531 // \\531 \\ var val: MyEnum = .Two;
532 // \\pub export fn _start() u32 {532 \\ var a: u32 = switch (val) {
533 // \\ var val: MyEnum = .Two;533 \\ .One => 1,
534 // \\ var a: u32 = switch (val) {534 \\ .Two => 2,
535 // \\ .One => 1,535 \\ .Three => 3,
536 // \\ .Two => 2,536 \\ };
537 // \\ .Three => 3,537 \\
538 // \\ };538 \\ return a;
539 // \\539 \\}
540 // \\ return a;540 , "2\n");
541 // \\}541 }
542 // , "2\n");
543 //}
544542
545 {543 {
546 var case = ctx.exe("wasm error unions", wasi);544 var case = ctx.exe("wasm error unions", wasi);