Fix a bunch of disparate issues around integers
e0e2e01d246021251f5d5272f33ae2b84ee7e891f1e1f79a2ed614c072a4a05f
Use 64-bit integers by default.
1 parent
a1e8824d
lib/std/lang/lower.rad
+11 -6
| 5884 | 5884 | } |
|
| 5885 | 5885 | ||
| 5886 | 5886 | /// Check whether a resolver type is a signed integer type. |
|
| 5887 | 5887 | fn isSignedType(t: resolver::Type) -> bool { |
|
| 5888 | 5888 | match t { |
|
| 5889 | - | case resolver::Type::I8, resolver::Type::I16, resolver::Type::I32, resolver::Type::I64 => return true, |
|
| 5889 | + | case resolver::Type::I8, resolver::Type::I16, resolver::Type::I32, resolver::Type::I64, |
|
| 5890 | + | resolver::Type::Int => return true, |
|
| 5890 | 5891 | else => return false, |
|
| 5891 | 5892 | } |
|
| 5892 | 5893 | } |
|
| 5893 | 5894 | ||
| 5894 | 5895 | /// Check whether a resolver type is an unsigned integer type. |
| 7011 | 7012 | if resolver::isVoidUnion(typ) { |
|
| 7012 | 7013 | return il::Type::W8; |
|
| 7013 | 7014 | } |
|
| 7014 | 7015 | return il::Type::W64; |
|
| 7015 | 7016 | } |
|
| 7016 | - | case resolver::Type::Void, |
|
| 7017 | - | // FIXME: We shouldn't try to lower this type, it should be behind a pointer. |
|
| 7018 | - | resolver::Type::Opaque, |
|
| 7019 | - | // FIXME: This should be resolved to a concrete integer type in the resolver. |
|
| 7020 | - | resolver::Type::Int => return il::Type::W32, |
|
| 7017 | + | case resolver::Type::Void => return il::Type::W64, |
|
| 7018 | + | // [`Type::Int`] is the type of unsuffixed integer literals and their |
|
| 7019 | + | // compound expressions (e.g. `1 + 2`). It defaults to W64 (i64) here, |
|
| 7020 | + | // matching the native word size on RV64. It cannot be resolved earlier |
|
| 7021 | + | // because the resolver uses [`Type::Int`] to distinguish unsuffixed |
|
| 7022 | + | // expressions from explicitly typed ones, which affects coercion |
|
| 7023 | + | // behavior (e.g. implicit narrowing). |
|
| 7024 | + | case resolver::Type::Int => return il::Type::W64, |
|
| 7025 | + | case resolver::Type::Opaque => panic "ilType: opaque type must be behind a pointer", |
|
| 7021 | 7026 | else => panic "ilType: type cannot be lowered", |
|
| 7022 | 7027 | } |
|
| 7023 | 7028 | } |
lib/std/lang/parser.rad
+0 -1
| 1184 | 1184 | return p.current.kind == kind; |
|
| 1185 | 1185 | } |
|
| 1186 | 1186 | ||
| 1187 | 1187 | /// Advance the parser by one token. |
|
| 1188 | 1188 | pub fn advance(p: *mut Parser) { |
|
| 1189 | - | // FIXME: `previous` is garbage the first time this function is called. |
|
| 1190 | 1189 | p.previous = p.current; |
|
| 1191 | 1190 | p.current = scanner::next(&mut p.scanner); |
|
| 1192 | 1191 | } |
|
| 1193 | 1192 | ||
| 1194 | 1193 | /// Parse an `if let` pattern matching statement. |
lib/std/lang/resolver.rad
+32 -8
| 1347 | 1347 | pub fn getTypeLayout(ty: Type) -> Layout { |
|
| 1348 | 1348 | match ty { |
|
| 1349 | 1349 | case Type::Void, Type::Never => return Layout { size: 0, alignment: 0 }, |
|
| 1350 | 1350 | case Type::Bool, Type::U8, Type::I8 => return Layout { size: 1, alignment: 1 }, |
|
| 1351 | 1351 | case Type::U16, Type::I16 => return Layout { size: 2, alignment: 2 }, |
|
| 1352 | - | case Type::U32, Type::I32, Type::Int => return Layout { size: 4, alignment: 4 }, |
|
| 1352 | + | case Type::U32, Type::I32 => return Layout { size: 4, alignment: 4 }, |
|
| 1353 | + | case Type::Int => return Layout { size: 8, alignment: 8 }, |
|
| 1353 | 1354 | case Type::U64, Type::I64 => return Layout { size: 8, alignment: 8 }, |
|
| 1354 | 1355 | case Type::Pointer { .. }, |
|
| 1355 | 1356 | Type::Fn(_) => return Layout { size: PTR_SIZE, alignment: PTR_SIZE }, |
|
| 1356 | 1357 | case Type::Slice { .. }, |
|
| 1357 | 1358 | Type::TraitObject { .. } => return Layout { size: PTR_SIZE * 2, alignment: PTR_SIZE }, |
| 1542 | 1543 | bits: 16, |
|
| 1543 | 1544 | min: I16_MIN as i64, |
|
| 1544 | 1545 | max: I16_MAX as i64, |
|
| 1545 | 1546 | lim: (I16_MAX as u64) + 1, |
|
| 1546 | 1547 | }, |
|
| 1547 | - | case Type::I32, |
|
| 1548 | - | Type::Int => return IntegerRange::Signed { |
|
| 1548 | + | case Type::I32 => return IntegerRange::Signed { |
|
| 1549 | 1549 | bits: 32, |
|
| 1550 | 1550 | min: I32_MIN as i64, |
|
| 1551 | 1551 | max: I32_MAX as i64, |
|
| 1552 | 1552 | lim: (I32_MAX as u64) + 1, |
|
| 1553 | 1553 | }, |
|
| 1554 | - | case Type::I64 => return IntegerRange::Signed { |
|
| 1554 | + | case Type::I64, Type::Int => return IntegerRange::Signed { |
|
| 1555 | 1555 | bits: 64, |
|
| 1556 | 1556 | min: I64_MIN, |
|
| 1557 | 1557 | max: I64_MAX, |
|
| 1558 | 1558 | lim: (I64_MAX as u64) + 1, |
|
| 1559 | 1559 | }, |
| 1796 | 1796 | if validateConstIntRange(value, to) { |
|
| 1797 | 1797 | return Coercion::Identity; |
|
| 1798 | 1798 | } |
|
| 1799 | 1799 | return nil; |
|
| 1800 | 1800 | } |
|
| 1801 | + | // Folded constant expression (e.g. `1 + 2`): if the |
|
| 1802 | + | // result fits the target, use identity. Otherwise allow |
|
| 1803 | + | // wrapping via numeric cast. |
|
| 1804 | + | if validateConstIntRange(value, to) { |
|
| 1805 | + | return Coercion::Identity; |
|
| 1806 | + | } |
|
| 1801 | 1807 | } |
|
| 1802 | 1808 | // Allow unsuffixed integer expressions to be inferred from context. |
|
| 1803 | 1809 | if from == Type::Int { |
|
| 1804 | 1810 | return Coercion::NumericCast { from, to }; |
|
| 1805 | 1811 | } |
| 2663 | 2669 | return setNodeType(self, node, *sliceTy); |
|
| 2664 | 2670 | }, |
|
| 2665 | 2671 | case ast::NodeValue::Number(lit) => { |
|
| 2666 | 2672 | setNodeConstValue(self, node, ConstValue::Int(ConstInt { |
|
| 2667 | 2673 | magnitude: lit.magnitude, |
|
| 2668 | - | bits: 32, |
|
| 2674 | + | bits: 64, |
|
| 2669 | 2675 | signed: lit.signed, |
|
| 2670 | 2676 | negative: lit.negative, |
|
| 2671 | 2677 | })); |
|
| 2672 | 2678 | return setNodeType(self, node, Type::Int); |
|
| 2673 | 2679 | }, |
| 5438 | 5444 | let length = items.len; |
|
| 5439 | 5445 | let mut expectedTy: Type = Type::Unknown; |
|
| 5440 | 5446 | ||
| 5441 | 5447 | if let case Type::Array(ary) = hint { |
|
| 5442 | 5448 | expectedTy = *ary.item; |
|
| 5449 | + | } else if let case Type::Optional(inner) = hint { |
|
| 5450 | + | if let case Type::Array(ary) = *inner { |
|
| 5451 | + | expectedTy = *ary.item; |
|
| 5452 | + | } |
|
| 5443 | 5453 | }; |
|
| 5444 | 5454 | for itemNode in items { |
|
| 5445 | 5455 | let itemTy = try visit(self, itemNode, expectedTy); |
|
| 5446 | 5456 | assert itemTy != Type::Unknown; |
|
| 5447 | 5457 |
| 5461 | 5471 | ||
| 5462 | 5472 | /// Analyze an array repeat literal expression. |
|
| 5463 | 5473 | fn resolveArrayRepeat(self: *mut Resolver, node: *ast::Node, lit: ast::ArrayRepeatLit, hint: Type) -> Type |
|
| 5464 | 5474 | throws (ResolveError) |
|
| 5465 | 5475 | { |
|
| 5466 | - | let valueTy = try visit(self, lit.item, hint); |
|
| 5476 | + | let mut itemHint = hint; |
|
| 5477 | + | if let case Type::Array(ary) = hint { |
|
| 5478 | + | itemHint = *ary.item; |
|
| 5479 | + | } else if let case Type::Optional(inner) = hint { |
|
| 5480 | + | if let case Type::Array(ary) = *inner { |
|
| 5481 | + | itemHint = *ary.item; |
|
| 5482 | + | } |
|
| 5483 | + | } |
|
| 5484 | + | let valueTy = try visit(self, lit.item, itemHint); |
|
| 5467 | 5485 | let count = try checkSizeInt(self, lit.count); |
|
| 5468 | 5486 | let arrayTy = Type::Array(ArrayType { |
|
| 5469 | 5487 | item: allocType(self, valueTy), |
|
| 5470 | 5488 | length: count, |
|
| 5471 | 5489 | }); |
| 5614 | 5632 | let fieldName = try nodeName(self, access.child); |
|
| 5615 | 5633 | if let method = findMethod(self, subjectTy, fieldName) { |
|
| 5616 | 5634 | return setNodeType(self, node, Type::Fn(method.fnType)); |
|
| 5617 | 5635 | } |
|
| 5618 | 5636 | } |
|
| 5637 | + | throw emitError(self, access.parent, ErrorKind::ExpectedRecord); |
|
| 5619 | 5638 | } |
|
| 5620 | 5639 | } |
|
| 5621 | - | // FIXME: We can't move this to the `else` branch due to a resolver bug. |
|
| 5622 | - | throw emitError(self, access.parent, ErrorKind::ExpectedRecord); |
|
| 5623 | 5640 | } |
|
| 5624 | 5641 | ||
| 5625 | 5642 | /// Determine whether an expression can yield a mutable location for borrowing. |
|
| 5626 | 5643 | fn canBorrowMutFrom(self: *mut Resolver, node: *ast::Node) -> bool |
|
| 5627 | 5644 | throws (ResolveError) |
| 6378 | 6395 | } |
|
| 6379 | 6396 | } |
|
| 6380 | 6397 | }, |
|
| 6381 | 6398 | case ast::UnaryOp::BitNot => { |
|
| 6382 | 6399 | resultTy = try checkNumeric(self, unop.value); |
|
| 6400 | + | if let value = constValueFor(self, unop.value) { |
|
| 6401 | + | if let case ConstValue::Int(intVal) = value { |
|
| 6402 | + | let signed = constIntToSigned(intVal); |
|
| 6403 | + | let inverted = constIntFromSigned(-(signed + 1), intVal.bits, intVal.signed); |
|
| 6404 | + | setNodeConstValue(self, node, ConstValue::Int(inverted)); |
|
| 6405 | + | } |
|
| 6406 | + | } |
|
| 6383 | 6407 | }, |
|
| 6384 | 6408 | }; |
|
| 6385 | 6409 | return setNodeType(self, node, resultTy); |
|
| 6386 | 6410 | } |
|
| 6387 | 6411 |
test/tests/binop.bitwise.rad
+10 -10
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | @default fn main() -> i32 { |
|
| 3 | 3 | // Test `&` (bitwise AND). |
|
| 4 | 4 | // `12 = 0b1100`, `10 = 0b1010`, result = `0b1000 = 8`. |
|
| 5 | - | let a: i32 = 12 & 10; |
|
| 5 | + | let a: i64 = 12 & 10; |
|
| 6 | 6 | assert a == 8; |
|
| 7 | 7 | ||
| 8 | 8 | // Test `|` (bitwise OR). |
|
| 9 | 9 | // `12 = 0b1100`, `10 = 0b1010`, result = `0b1110 = 14`. |
|
| 10 | - | let b: i32 = 12 | 10; |
|
| 10 | + | let b: i64 = 12 | 10; |
|
| 11 | 11 | assert b == 14; |
|
| 12 | 12 | ||
| 13 | 13 | // Test `^` (bitwise XOR). |
|
| 14 | 14 | // `12 = 0b1100`, `10 = 0b1010`, result = `0b0110 = 6`. |
|
| 15 | - | let c: i32 = 12 ^ 10; |
|
| 15 | + | let c: i64 = 12 ^ 10; |
|
| 16 | 16 | assert c == 6; |
|
| 17 | 17 | ||
| 18 | 18 | // Test `<<` (shift left). |
|
| 19 | 19 | // `3 << 4 = 48`. |
|
| 20 | - | let d: i32 = 3 << 4; |
|
| 20 | + | let d: i64 = 3 << 4; |
|
| 21 | 21 | assert d == 48; |
|
| 22 | 22 | ||
| 23 | 23 | // Test `>>` (shift right, arithmetic for signed). |
|
| 24 | 24 | // `48 >> 2 = 12`. |
|
| 25 | - | let e: i32 = 48 >> 2; |
|
| 25 | + | let e: i64 = 48 >> 2; |
|
| 26 | 26 | assert e == 12; |
|
| 27 | 27 | ||
| 28 | 28 | // Test `>>` with negative (arithmetic shift preserves sign). |
|
| 29 | 29 | // `-16 >> 2 = -4` (sign bit extended). |
|
| 30 | - | let f: i32 = -16 >> 2; |
|
| 30 | + | let f: i64 = -16 >> 2; |
|
| 31 | 31 | assert f == -4; |
|
| 32 | 32 | ||
| 33 | 33 | // Test `~` (bitwise NOT). |
|
| 34 | 34 | // `~0 = -1` (all bits set). |
|
| 35 | - | let g: i32 = ~0; |
|
| 35 | + | let g: i64 = ~0; |
|
| 36 | 36 | assert g == -1; |
|
| 37 | 37 | ||
| 38 | 38 | // Test `~` with positive value. |
|
| 39 | 39 | // `~1 = -2` (in two's complement). |
|
| 40 | - | let h: i32 = ~1; |
|
| 40 | + | let h: i64 = ~1; |
|
| 41 | 41 | assert h == -2; |
|
| 42 | 42 | ||
| 43 | 43 | // Combined operations. |
|
| 44 | 44 | // `(5 | 3) & 6 = 7 & 6 = 6`. |
|
| 45 | - | let i: i32 = (5 | 3) & 6; |
|
| 45 | + | let i: i64 = (5 | 3) & 6; |
|
| 46 | 46 | assert i == 6; |
|
| 47 | 47 | ||
| 48 | 48 | // XOR self is `0`. |
|
| 49 | - | let j: i32 = 42; |
|
| 49 | + | let j: i64 = 42; |
|
| 50 | 50 | assert (j ^ j) == 0; |
|
| 51 | 51 | return 0; |
|
| 52 | 52 | } |
test/tests/binop.bitwise.ril
+21 -22
| 1 | 1 | fn w32 $main() { |
|
| 2 | 2 | @entry0 |
|
| 3 | - | and w32 %0 12 10; |
|
| 4 | - | br.eq w32 %0 8 @assert.ok2 @assert.fail1; |
|
| 3 | + | and w64 %0 12 10; |
|
| 4 | + | br.eq w64 %0 8 @assert.ok2 @assert.fail1; |
|
| 5 | 5 | @assert.fail1 |
|
| 6 | 6 | unreachable; |
|
| 7 | 7 | @assert.ok2 |
|
| 8 | - | or w32 %1 12 10; |
|
| 9 | - | br.eq w32 %1 14 @assert.ok4 @assert.fail3; |
|
| 8 | + | or w64 %1 12 10; |
|
| 9 | + | br.eq w64 %1 14 @assert.ok4 @assert.fail3; |
|
| 10 | 10 | @assert.fail3 |
|
| 11 | 11 | unreachable; |
|
| 12 | 12 | @assert.ok4 |
|
| 13 | - | xor w32 %2 12 10; |
|
| 14 | - | br.eq w32 %2 6 @assert.ok6 @assert.fail5; |
|
| 13 | + | xor w64 %2 12 10; |
|
| 14 | + | br.eq w64 %2 6 @assert.ok6 @assert.fail5; |
|
| 15 | 15 | @assert.fail5 |
|
| 16 | 16 | unreachable; |
|
| 17 | 17 | @assert.ok6 |
|
| 18 | - | shl w32 %3 3 4; |
|
| 19 | - | br.eq w32 %3 48 @assert.ok8 @assert.fail7; |
|
| 18 | + | shl w64 %3 3 4; |
|
| 19 | + | br.eq w64 %3 48 @assert.ok8 @assert.fail7; |
|
| 20 | 20 | @assert.fail7 |
|
| 21 | 21 | unreachable; |
|
| 22 | 22 | @assert.ok8 |
|
| 23 | - | sshr w32 %4 48 2; |
|
| 24 | - | br.eq w32 %4 12 @assert.ok10 @assert.fail9; |
|
| 23 | + | sshr w64 %4 48 2; |
|
| 24 | + | br.eq w64 %4 12 @assert.ok10 @assert.fail9; |
|
| 25 | 25 | @assert.fail9 |
|
| 26 | 26 | unreachable; |
|
| 27 | 27 | @assert.ok10 |
|
| 28 | - | sshr w32 %5 -16 2; |
|
| 29 | - | br.eq w32 %5 -4 @assert.ok12 @assert.fail11; |
|
| 28 | + | sshr w64 %5 -16 2; |
|
| 29 | + | br.eq w64 %5 -4 @assert.ok12 @assert.fail11; |
|
| 30 | 30 | @assert.fail11 |
|
| 31 | 31 | unreachable; |
|
| 32 | 32 | @assert.ok12 |
|
| 33 | - | not w32 %6 0; |
|
| 34 | - | br.eq w32 %6 -1 @assert.ok14 @assert.fail13; |
|
| 33 | + | not w64 %6 0; |
|
| 34 | + | br.eq w64 %6 -1 @assert.ok14 @assert.fail13; |
|
| 35 | 35 | @assert.fail13 |
|
| 36 | 36 | unreachable; |
|
| 37 | 37 | @assert.ok14 |
|
| 38 | - | not w32 %7 1; |
|
| 39 | - | br.eq w32 %7 -2 @assert.ok16 @assert.fail15; |
|
| 38 | + | not w64 %7 1; |
|
| 39 | + | br.eq w64 %7 -2 @assert.ok16 @assert.fail15; |
|
| 40 | 40 | @assert.fail15 |
|
| 41 | 41 | unreachable; |
|
| 42 | 42 | @assert.ok16 |
|
| 43 | - | or w32 %8 5 3; |
|
| 44 | - | and w32 %9 %8 6; |
|
| 45 | - | br.eq w32 %9 6 @assert.ok18 @assert.fail17; |
|
| 43 | + | or w64 %8 5 3; |
|
| 44 | + | and w64 %9 %8 6; |
|
| 45 | + | br.eq w64 %9 6 @assert.ok18 @assert.fail17; |
|
| 46 | 46 | @assert.fail17 |
|
| 47 | 47 | unreachable; |
|
| 48 | 48 | @assert.ok18 |
|
| 49 | - | xor w32 %10 42 42; |
|
| 50 | - | br.eq w32 %10 0 @assert.ok20 @assert.fail19; |
|
| 49 | + | xor w64 %10 42 42; |
|
| 50 | + | br.eq w64 %10 0 @assert.ok20 @assert.fail19; |
|
| 51 | 51 | @assert.fail19 |
|
| 52 | 52 | unreachable; |
|
| 53 | 53 | @assert.ok20 |
|
| 54 | 54 | ret 0; |
|
| 55 | 55 | } |
|
| 56 | - |
test/tests/byte.load.store.ril
+2 -2
| 2 | 2 | @entry0 |
|
| 3 | 3 | load w8 %1 %0 0; |
|
| 4 | 4 | ret %1; |
|
| 5 | 5 | } |
|
| 6 | 6 | ||
| 7 | - | fn w32 $storeByte(w64 %0, w8 %1) { |
|
| 7 | + | fn w64 $storeByte(w64 %0, w8 %1) { |
|
| 8 | 8 | @entry0 |
|
| 9 | 9 | store w8 %1 %0 0; |
|
| 10 | 10 | ret; |
|
| 11 | 11 | } |
|
| 12 | 12 | ||
| 13 | - | fn w32 $loadStoreByte(w64 %0, w64 %1) { |
|
| 13 | + | fn w64 $loadStoreByte(w64 %0, w64 %1) { |
|
| 14 | 14 | @entry0 |
|
| 15 | 15 | load w8 %2 %0 0; |
|
| 16 | 16 | store w8 %2 %1 0; |
|
| 17 | 17 | ret; |
|
| 18 | 18 | } |
test/tests/call.tests.ril
+2 -2
| 13 | 13 | @entry0 |
|
| 14 | 14 | add w32 %2 %0 %1; |
|
| 15 | 15 | ret %2; |
|
| 16 | 16 | } |
|
| 17 | 17 | ||
| 18 | - | fn w32 $doNothing() { |
|
| 18 | + | fn w64 $doNothing() { |
|
| 19 | 19 | @entry0 |
|
| 20 | 20 | ret; |
|
| 21 | 21 | } |
|
| 22 | 22 | ||
| 23 | 23 | fn w32 $callSimple(w32 %0) { |
| 34 | 34 | ret %4; |
|
| 35 | 35 | } |
|
| 36 | 36 | ||
| 37 | 37 | fn w32 $callVoid() { |
|
| 38 | 38 | @entry0 |
|
| 39 | - | call w32 $doNothing(); |
|
| 39 | + | call w64 $doNothing(); |
|
| 40 | 40 | ret 1; |
|
| 41 | 41 | } |
|
| 42 | 42 | ||
| 43 | 43 | fn w32 $callAndIgnore() { |
|
| 44 | 44 | @entry0 |
test/tests/cond.expr.rad
+2 -2
| 15 | 15 | return Color::Red if isRed else Color::Blue; |
|
| 16 | 16 | } |
|
| 17 | 17 | ||
| 18 | 18 | /// Test basic scalar conditional expression. |
|
| 19 | 19 | fn testScalar() -> i32 { |
|
| 20 | - | let x: i32 = 10 if true else 20; |
|
| 20 | + | let x: i64 = 10 if true else 20; |
|
| 21 | 21 | assert x == 10; |
|
| 22 | - | let y: i32 = 10 if false else 20; |
|
| 22 | + | let y: i64 = 10 if false else 20; |
|
| 23 | 23 | assert y == 20; |
|
| 24 | 24 | return 0; |
|
| 25 | 25 | } |
|
| 26 | 26 | ||
| 27 | 27 | /// Test min-value pattern. |
test/tests/cond.expr.ril
+4 -5
| 37 | 37 | br.ne w32 %0 0 @cond#then1 @cond#else2; |
|
| 38 | 38 | @cond#then1 |
|
| 39 | 39 | jmp @cond#merge3(10); |
|
| 40 | 40 | @cond#else2 |
|
| 41 | 41 | jmp @cond#merge3(20); |
|
| 42 | - | @cond#merge3(w32 %1) |
|
| 43 | - | br.eq w32 %1 10 @assert.ok5 @assert.fail4; |
|
| 42 | + | @cond#merge3(w64 %1) |
|
| 43 | + | br.eq w64 %1 10 @assert.ok5 @assert.fail4; |
|
| 44 | 44 | @assert.fail4 |
|
| 45 | 45 | unreachable; |
|
| 46 | 46 | @assert.ok5 |
|
| 47 | 47 | copy %2 0; |
|
| 48 | 48 | br.ne w32 %2 0 @cond#then6 @cond#else7; |
|
| 49 | 49 | @cond#then6 |
|
| 50 | 50 | jmp @cond#merge8(10); |
|
| 51 | 51 | @cond#else7 |
|
| 52 | 52 | jmp @cond#merge8(20); |
|
| 53 | - | @cond#merge8(w32 %3) |
|
| 54 | - | br.eq w32 %3 20 @assert.ok10 @assert.fail9; |
|
| 53 | + | @cond#merge8(w64 %3) |
|
| 54 | + | br.eq w64 %3 20 @assert.ok10 @assert.fail9; |
|
| 55 | 55 | @assert.fail9 |
|
| 56 | 56 | unreachable; |
|
| 57 | 57 | @assert.ok10 |
|
| 58 | 58 | ret 0; |
|
| 59 | 59 | } |
| 176 | 176 | @then9 |
|
| 177 | 177 | ret %4; |
|
| 178 | 178 | @merge10 |
|
| 179 | 179 | ret 0; |
|
| 180 | 180 | } |
|
| 181 | - |
test/tests/int.default.i64.rad
added
+58 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | //! Test that unsuffixed integer literals default to 64-bit (i64). |
|
| 3 | + | ||
| 4 | + | /// Test basic arithmetic on unsuffixed integers. |
|
| 5 | + | fn testArith() -> i32 { |
|
| 6 | + | let x: i64 = 1 + 2; |
|
| 7 | + | assert x == 3; |
|
| 8 | + | ||
| 9 | + | let y: i64 = 100 * 100; |
|
| 10 | + | assert y == 10000; |
|
| 11 | + | ||
| 12 | + | // Large value that doesn't fit in 32 bits. |
|
| 13 | + | let z: i64 = 2147483648; |
|
| 14 | + | assert z == 2147483648; |
|
| 15 | + | ||
| 16 | + | return 0; |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | /// Test unsuffixed integer coercion to i32. |
|
| 20 | + | fn testCoerceI32() -> i32 { |
|
| 21 | + | let x: i32 = 42; |
|
| 22 | + | assert x == 42; |
|
| 23 | + | ||
| 24 | + | let y: i32 = 1 + 2; |
|
| 25 | + | assert y == 3; |
|
| 26 | + | ||
| 27 | + | return 0; |
|
| 28 | + | } |
|
| 29 | + | ||
| 30 | + | /// Test unsuffixed integer coercion to i8. |
|
| 31 | + | fn testCoerceI8() -> i32 { |
|
| 32 | + | let x: i8 = 42; |
|
| 33 | + | assert x == 42; |
|
| 34 | + | ||
| 35 | + | let y: i8 = 1 + 2; |
|
| 36 | + | assert y == 3; |
|
| 37 | + | ||
| 38 | + | return 0; |
|
| 39 | + | } |
|
| 40 | + | ||
| 41 | + | /// Test unsuffixed integer in conditional expression. |
|
| 42 | + | fn testCondExpr() -> i32 { |
|
| 43 | + | let x: i64 = 10 if true else 20; |
|
| 44 | + | assert x == 10; |
|
| 45 | + | ||
| 46 | + | let y: i32 = 10 if false else 20; |
|
| 47 | + | assert y == 20; |
|
| 48 | + | ||
| 49 | + | return 0; |
|
| 50 | + | } |
|
| 51 | + | ||
| 52 | + | @default fn main() -> i32 { |
|
| 53 | + | assert testArith() == 0; |
|
| 54 | + | assert testCoerceI32() == 0; |
|
| 55 | + | assert testCoerceI8() == 0; |
|
| 56 | + | assert testCondExpr() == 0; |
|
| 57 | + | return 0; |
|
| 58 | + | } |
test/tests/intrinsic.ebreak.ril
+2 -2
| 1 | - | extern fn w32 $ebreak(); |
|
| 1 | + | extern fn w64 $ebreak(); |
|
| 2 | 2 | ||
| 3 | - | fn w32 $test() { |
|
| 3 | + | fn w64 $test() { |
|
| 4 | 4 | @entry0 |
|
| 5 | 5 | ebreak; |
|
| 6 | 6 | ret; |
|
| 7 | 7 | } |
test/tests/multiplefns.ril
+1 -1
| 6 | 6 | fn w32 $second(w32 %0, w32 %1) { |
|
| 7 | 7 | @entry0 |
|
| 8 | 8 | ret %0; |
|
| 9 | 9 | } |
|
| 10 | 10 | ||
| 11 | - | fn w32 $third() { |
|
| 11 | + | fn w64 $third() { |
|
| 12 | 12 | @entry0 |
|
| 13 | 13 | ret; |
|
| 14 | 14 | } |
test/tests/mutref.loop.ril
+2 -2
| 1 | - | fn w32 $callback(w32 %0, w64 %1) { |
|
| 1 | + | fn w64 $callback(w32 %0, w64 %1) { |
|
| 2 | 2 | @entry0 |
|
| 3 | 3 | store w32 %0 %1 0; |
|
| 4 | 4 | ret; |
|
| 5 | 5 | } |
|
| 6 | 6 |
| 10 | 10 | store w32 0 %0 0; |
|
| 11 | 11 | jmp @while1(0, %0); |
|
| 12 | 12 | @while1(w32 %1, w32 %2) |
|
| 13 | 13 | br.ult w32 %1 3 @body2 @merge3; |
|
| 14 | 14 | @body2 |
|
| 15 | - | call w32 $callback(%1, %2); |
|
| 15 | + | call w64 $callback(%1, %2); |
|
| 16 | 16 | add w32 %3 %1 1; |
|
| 17 | 17 | jmp @while1(%3, %2); |
|
| 18 | 18 | @merge3 |
|
| 19 | 19 | load w32 %4 %2 0; |
|
| 20 | 20 | ret %4; |
test/tests/opt.array.hint.rad
added
+45 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | //! Test that array literal type hints propagate through optionals. |
|
| 3 | + | ||
| 4 | + | /// Return an optional array literal. |
|
| 5 | + | fn optArray() -> ?[i32; 3] { |
|
| 6 | + | return [1, 2, 3]; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// Return an optional array repeat literal. |
|
| 10 | + | fn optRepeat() -> ?[i32; 4] { |
|
| 11 | + | return [0; 4]; |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | /// Test optional array literal hint propagation. |
|
| 15 | + | fn testOptArrayLit() -> i32 { |
|
| 16 | + | if let a = optArray() { |
|
| 17 | + | assert a.len == 3; |
|
| 18 | + | assert a[0] == 1; |
|
| 19 | + | assert a[1] == 2; |
|
| 20 | + | assert a[2] == 3; |
|
| 21 | + | } else { |
|
| 22 | + | return 1; |
|
| 23 | + | } |
|
| 24 | + | return 0; |
|
| 25 | + | } |
|
| 26 | + | ||
| 27 | + | /// Test optional array repeat literal hint propagation. |
|
| 28 | + | fn testOptRepeat() -> i32 { |
|
| 29 | + | if let a = optRepeat() { |
|
| 30 | + | assert a.len == 4; |
|
| 31 | + | assert a[0] == 0; |
|
| 32 | + | assert a[1] == 0; |
|
| 33 | + | assert a[2] == 0; |
|
| 34 | + | assert a[3] == 0; |
|
| 35 | + | } else { |
|
| 36 | + | return 1; |
|
| 37 | + | } |
|
| 38 | + | return 0; |
|
| 39 | + | } |
|
| 40 | + | ||
| 41 | + | @default fn main() -> i32 { |
|
| 42 | + | assert testOptArrayLit() == 0; |
|
| 43 | + | assert testOptRepeat() == 0; |
|
| 44 | + | return 0; |
|
| 45 | + | } |
test/tests/ptr.subscript.assign.ril
+1 -1
| 1 | - | fn w32 $subscriptAssign(w64 %0, w32 %1, w32 %2) { |
|
| 1 | + | fn w64 $subscriptAssign(w64 %0, w32 %1, w32 %2) { |
|
| 2 | 2 | @entry0 |
|
| 3 | 3 | load w32 %3 %0 8; |
|
| 4 | 4 | br.ult w32 %1 %3 @guard#pass1 @guard#trap2; |
|
| 5 | 5 | @guard#pass1 |
|
| 6 | 6 | load w64 %4 %0 0; |
test/tests/record.assign.blit.ril
+1 -1
| 1 | - | fn w32 $copy() { |
|
| 1 | + | fn w64 $copy() { |
|
| 2 | 2 | @entry0 |
|
| 3 | 3 | reserve %0 8 4; |
|
| 4 | 4 | store w32 1 %0 0; |
|
| 5 | 5 | store w32 2 %0 4; |
|
| 6 | 6 | reserve %1 8 4; |
test/tests/slice.mutable.ril
+3 -3
| 1 | - | fn w32 $mutSliceStore(w64 %0, w32 %1, w32 %2) { |
|
| 1 | + | fn w64 $mutSliceStore(w64 %0, w32 %1, w32 %2) { |
|
| 2 | 2 | @entry0 |
|
| 3 | 3 | load w32 %3 %0 8; |
|
| 4 | 4 | br.ult w32 %1 %3 @guard#pass1 @guard#trap2; |
|
| 5 | 5 | @guard#pass1 |
|
| 6 | 6 | load w64 %4 %0 0; |
| 11 | 11 | @guard#trap2 |
|
| 12 | 12 | ebreak; |
|
| 13 | 13 | unreachable; |
|
| 14 | 14 | } |
|
| 15 | 15 | ||
| 16 | - | fn w32 $mutSliceIncrement(w64 %0, w32 %1) { |
|
| 16 | + | fn w64 $mutSliceIncrement(w64 %0, w32 %1) { |
|
| 17 | 17 | @entry0 |
|
| 18 | 18 | load w32 %2 %0 8; |
|
| 19 | 19 | br.ult w32 %1 %2 @guard#pass1 @guard#trap2; |
|
| 20 | 20 | @guard#pass1 |
|
| 21 | 21 | load w64 %3 %0 0; |
| 37 | 37 | @guard#trap4 |
|
| 38 | 38 | ebreak; |
|
| 39 | 39 | unreachable; |
|
| 40 | 40 | } |
|
| 41 | 41 | ||
| 42 | - | fn w32 $mutSliceSwap(w64 %0, w32 %1, w32 %2) { |
|
| 42 | + | fn w64 $mutSliceSwap(w64 %0, w32 %1, w32 %2) { |
|
| 43 | 43 | @entry0 |
|
| 44 | 44 | load w32 %3 %0 8; |
|
| 45 | 45 | br.ult w32 %1 %3 @guard#pass1 @guard#trap2; |
|
| 46 | 46 | @guard#pass1 |
|
| 47 | 47 | load w64 %4 %0 0; |
test/tests/trait.dispatch.ril
+2 -2
| 7 | 7 | @entry0 |
|
| 8 | 8 | sload w32 %1 %0 0; |
|
| 9 | 9 | ret %1; |
|
| 10 | 10 | } |
|
| 11 | 11 | ||
| 12 | - | fn w32 $"Acc::set"(w64 %0, w32 %1) { |
|
| 12 | + | fn w64 $"Acc::set"(w64 %0, w32 %1) { |
|
| 13 | 13 | @entry0 |
|
| 14 | 14 | store w32 %1 %0 0; |
|
| 15 | 15 | ret; |
|
| 16 | 16 | } |
|
| 17 | 17 | ||
| 18 | 18 | fn w32 $dispatch(w64 %0) { |
|
| 19 | 19 | @entry0 |
|
| 20 | 20 | load w64 %1 %0 0; |
|
| 21 | 21 | load w64 %2 %0 8; |
|
| 22 | 22 | load w64 %3 %2 8; |
|
| 23 | - | call w32 %3(%1, 42); |
|
| 23 | + | call w64 %3(%1, 42); |
|
| 24 | 24 | load w64 %4 %0 0; |
|
| 25 | 25 | load w64 %5 %0 8; |
|
| 26 | 26 | load w64 %6 %5 0; |
|
| 27 | 27 | call w32 %7 %6(%4); |
|
| 28 | 28 | ret %7; |
test/tests/voidfn.ril
+1 -1
| 1 | - | fn w32 $doNothing() { |
|
| 1 | + | fn w64 $doNothing() { |
|
| 2 | 2 | @entry0 |
|
| 3 | 3 | ret; |
|
| 4 | 4 | } |