| author | |
| committer | |
| log | 30376a82b2c1b13047ff3b48391fcda44183e129 |
| tree | c8c30217017f3003303b077230fd02a798335151 |
| parent | 5d98abd5703607884844e8b8165dcc2238389c57 |
| signature | Commit is signed but in an unrecognized format. |
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 | } |
| 1086 | 1086 | ||
| 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 { |
| 1307 | 1343 | ||
| 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 value | 1362 | // 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; |
| 1338 | 1366 | ||
| 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 | } |
| 481 | 481 | ||
| 482 | // This test case is disabled until the codegen for switch is reworked | 482 | { |
| 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( |
| 486 | 486 | \\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( |
| 500 | 500 | \\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( |
| 514 | 514 | \\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( |
| 528 | 528 | \\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 | //} | ||
| 544 | 542 | ||
| 545 | { | 543 | { |
| 546 | var case = ctx.exe("wasm error unions", wasi); | 544 | var case = ctx.exe("wasm error unions", wasi); |