Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions xls/dslx/bytecode/builtins.cc
Original file line number Diff line number Diff line change
Expand Up @@ -518,24 +518,6 @@ absl::Status RunBuiltinCtz(const Bytecode& bytecode, InterpreterStack& stack) {
return absl::OkStatus();
}

absl::Status RunBuiltinEnumerate(const Bytecode& bytecode,
InterpreterStack& stack) {
XLS_RET_CHECK(!stack.empty());
XLS_ASSIGN_OR_RETURN(InterpValue input, stack.Pop());
XLS_ASSIGN_OR_RETURN(const std::vector<InterpValue>* values,
input.GetValues());

std::vector<InterpValue> elements;
elements.reserve(values->size());
for (int32_t i = 0; i < values->size(); i++) {
elements.push_back(
InterpValue::MakeTuple({InterpValue::MakeU32(i), values->at(i)}));
}
XLS_ASSIGN_OR_RETURN(InterpValue result, InterpValue::MakeArray(elements));
stack.Push(result);
return absl::OkStatus();
}

absl::Status RunBuiltinOrReduce(const Bytecode& bytecode,
InterpreterStack& stack) {
VLOG(3) << "Executing builtin OrReduce.";
Expand Down
2 changes: 0 additions & 2 deletions xls/dslx/bytecode/builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ absl::Status RunBuiltinCeilLog2(const Bytecode& bytecode,
absl::Status RunBuiltinClz(const Bytecode& bytecode, InterpreterStack& stack);
absl::Status RunBuiltinCover(const Bytecode& bytecode, InterpreterStack& stack);
absl::Status RunBuiltinCtz(const Bytecode& bytecode, InterpreterStack& stack);
absl::Status RunBuiltinEnumerate(const Bytecode& bytecode,
InterpreterStack& stack);
absl::Status RunBuiltinOrReduce(const Bytecode& bytecode,
InterpreterStack& stack);
absl::Status RunBuiltinRange(const Bytecode& bytecode, InterpreterStack& stack);
Expand Down
2 changes: 0 additions & 2 deletions xls/dslx/bytecode/bytecode_interpreter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1673,8 +1673,6 @@ absl::Status BytecodeInterpreter::RunBuiltinFn(const Bytecode& bytecode,
return RunBuiltinCover(bytecode, stack_);
case Builtin::kCtz:
return RunBuiltinCtz(bytecode, stack_);
case Builtin::kEnumerate:
return RunBuiltinEnumerate(bytecode, stack_);
case Builtin::kFail: {
XLS_ASSIGN_OR_RETURN(InterpValue value, Pop());
std::string message{value.ToString()};
Expand Down
23 changes: 0 additions & 23 deletions xls/dslx/bytecode/bytecode_interpreter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1940,29 +1940,6 @@ fn main(x: s10, y: s10) -> s10 {
EXPECT_THAT(bits.ToInt64(), IsOkAndHolds(-507));
}

TEST_F(BytecodeInterpreterTest, BuiltinEnumerate) {
constexpr std::string_view kProgram = R"(
fn main() -> (u32, u8)[4] {
let x = u8[4]:[5, 6, 7, 8];
enumerate(x)
})";

XLS_ASSERT_OK_AND_ASSIGN(InterpValue actual, Interpret(kProgram, "main"));
XLS_ASSERT_OK_AND_ASSIGN(
InterpValue expected,
InterpValue::MakeArray({
InterpValue::MakeTuple(
{InterpValue::MakeUBits(32, 0), InterpValue::MakeUBits(8, 5)}),
InterpValue::MakeTuple(
{InterpValue::MakeUBits(32, 1), InterpValue::MakeUBits(8, 6)}),
InterpValue::MakeTuple(
{InterpValue::MakeUBits(32, 2), InterpValue::MakeUBits(8, 7)}),
InterpValue::MakeTuple(
{InterpValue::MakeUBits(32, 3), InterpValue::MakeUBits(8, 8)}),
}));
EXPECT_TRUE(expected.Eq(actual));
}

TEST_F(BytecodeInterpreterTest, BuiltinUMulp) {
constexpr std::string_view kProgram = R"(
fn main(x: u10, y: u10) -> u10 {
Expand Down
1 change: 0 additions & 1 deletion xls/dslx/dslx_builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ namespace xls::dslx {
X("decode", kDecode) \
X("element_count", kElementCount) \
X("encode", kEncode) \
X("enumerate", kEnumerate) \
X("fail!", kFail) \
X("gate!", kGate) \
X("map", kMap) \
Expand Down
2 changes: 0 additions & 2 deletions xls/dslx/frontend/builtin_stubs.x
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ fn decode<T: type, N: u32>(x: uN[N]) -> T;

fn element_count<T: type>() -> u32;

fn enumerate<T: type, N: u32>(x: T[N]) -> (u32, T)[N];

fn fail!<N: u32, T: type> (label: u8[N], fallback_value: T) -> T;

fn gate!<T: type>(x: u1, y: T) -> T;
Expand Down
1 change: 0 additions & 1 deletion xls/dslx/frontend/builtins_metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ const absl::flat_hash_map<std::string, BuiltinsData>& GetParametricBuiltins() {
{"signex", {}},
{"array_slice", {}},
{"update", {}},
{"enumerate", {}},
{"widening_cast", {}},
{"checked_cast", {}},

Expand Down
23 changes: 10 additions & 13 deletions xls/dslx/ir_convert/testdata/ir_converter_test_ArrayEnumerate.ir
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,20 @@ package test_module
file_number 0 "xls/dslx/stdlib/std.x"
file_number 1 "test_module.x"

fn ____std__enumerate__4_u8_counted_for_0_body(i: bits[32] id=7, result: (bits[32], bits[8])[4] id=10, x: bits[8][4] id=11) -> (bits[32], bits[8])[4] {
literal.8: bits[32] = literal(value=0, id=8)
add.9: bits[32] = add(i, literal.8, id=9)
array_index.12: bits[8] = array_index(x, indices=[add.9], id=12)
tuple.13: (bits[32], bits[8]) = tuple(add.9, array_index.12, id=13)
ret array_update.14: (bits[32], bits[8])[4] = array_update(result, tuple.13, indices=[add.9], id=14)
fn ____std__enumerate__4_u8_counted_for_0_body(i: bits[32] id=4, result: (bits[32], bits[8])[4] id=7, x: bits[8][4] id=8) -> (bits[32], bits[8])[4] {
literal.5: bits[32] = literal(value=0, id=5)
add.6: bits[32] = add(i, literal.5, id=6)
array_index.9: bits[8] = array_index(x, indices=[add.6], id=9)
tuple.10: (bits[32], bits[8]) = tuple(add.6, array_index.9, id=10)
ret array_update.11: (bits[32], bits[8])[4] = array_update(result, tuple.10, indices=[add.6], id=11)
}

fn __std__enumerate__4_u8(x: bits[8][4] id=1) -> (bits[32], bits[8])[4] {
literal.3: bits[32] = literal(value=0, id=3)
literal.4: bits[8] = literal(value=0, id=4)
tuple.5: (bits[32], bits[8]) = tuple(literal.3, literal.4, id=5)
array.6: (bits[32], bits[8])[4] = array(tuple.5, tuple.5, tuple.5, tuple.5, id=6)
literal.3: (bits[32], bits[8])[4] = literal(value=[(0, 0), (0, 0), (0, 0), (0, 0)], id=3)
N: bits[32] = literal(value=4, id=2)
ret counted_for.15: (bits[32], bits[8])[4] = counted_for(array.6, trip_count=4, stride=1, body=____std__enumerate__4_u8_counted_for_0_body, invariant_args=[x], id=15)
ret counted_for.12: (bits[32], bits[8])[4] = counted_for(literal.3, trip_count=4, stride=1, body=____std__enumerate__4_u8_counted_for_0_body, invariant_args=[x], id=12)
}

top fn __test_module__main(array: bits[8][4] id=16) -> (bits[32], bits[8])[4] {
ret invoke.17: (bits[32], bits[8])[4] = invoke(array, to_apply=__std__enumerate__4_u8, id=17)
top fn __test_module__main(array: bits[8][4] id=13) -> (bits[32], bits[8])[4] {
ret invoke.14: (bits[32], bits[8])[4] = invoke(array, to_apply=__std__enumerate__4_u8, id=14)
}
44 changes: 43 additions & 1 deletion xls/dslx/stdlib/std.x
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
pub fn enumerate<T: type, N: u32>(x: T[N]) -> (u32, T)[N] {
for (i, result) in 0..N {
update(result, i, (i, x[i]))
}([(u32:0, zero!<T>()), ...])
}(zero!<(u32, T)[N]>())
}

#[test]
Expand All @@ -32,6 +32,13 @@ fn emumerate_test() {
assert_eq(enumerated[3], (3, 8));
}

#[test]
fn emumerate_empty_array_test() {
let empty_array: u32[0] = [];
let enumerated_empty = enumerate(empty_array);
assert_eq(enumerated_empty, []);
}

#[test]
fn enumerate_type_test() {
type RamData = uN[8];
Expand All @@ -51,6 +58,41 @@ fn enumerate_tuple_test() {
assert_eq(enumerated[1], (1, (false, 2)));
}

type TestIdx = uN[2];
type TestValue = uN[32];

struct TestData { idx: TestIdx, value: TestValue }

const TEST_DATA = TestData[20]:[
TestData { idx: TestIdx:0, value: TestValue:0xca32_9f4a },
TestData { idx: TestIdx:1, value: TestValue:0x0fb3_fa42 },
TestData { idx: TestIdx:2, value: TestValue:0xe7ee_da41 },
TestData { idx: TestIdx:3, value: TestValue:0xef51_f98c },
TestData { idx: TestIdx:0, value: TestValue:0x97a3_a2d2 },
TestData { idx: TestIdx:0, value: TestValue:0xea06_e94b },
TestData { idx: TestIdx:1, value: TestValue:0x5fac_17ce },
TestData { idx: TestIdx:3, value: TestValue:0xf9d8_9938 },
TestData { idx: TestIdx:2, value: TestValue:0xc262_2d2e },
TestData { idx: TestIdx:2, value: TestValue:0xb4dd_424e },
TestData { idx: TestIdx:1, value: TestValue:0x01f9_b9e4 },
TestData { idx: TestIdx:1, value: TestValue:0x3020_6eec },
TestData { idx: TestIdx:3, value: TestValue:0x3124_87b5 },
TestData { idx: TestIdx:0, value: TestValue:0x0a49_f5e3 },
TestData { idx: TestIdx:2, value: TestValue:0xde3b_5d0f },
TestData { idx: TestIdx:3, value: TestValue:0x5948_c1b3 },
TestData { idx: TestIdx:0, value: TestValue:0xa26d_851f },
TestData { idx: TestIdx:3, value: TestValue:0x3fa9_59c0 },
TestData { idx: TestIdx:1, value: TestValue:0x4efd_dd09 },
TestData { idx: TestIdx:1, value: TestValue:0x6d75_058a },
];

#[test]
fn enumerate_struct_test() {
let enumerated = enumerate(TEST_DATA);
assert_eq(enumerated[0], (0, TEST_DATA[0]));
assert_eq(enumerated[19], (19, TEST_DATA[19]));
}

pub fn sizeof<S: bool, N: u32>(x: xN[S][N]) -> u32 { N }

#[test]
Expand Down
6 changes: 0 additions & 6 deletions xls/dslx/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -338,12 +338,6 @@ dslx_lang_test(

dslx_lang_test(name = "for_over_range")

dslx_lang_test(
name = "enumerate",
compare = "interpreter",
convert_to_ir = True,
)

dslx_lang_test(
name = "character_conversion",
# TODO: https://github.com/google/xls/issues/1526 - fails opportunistic_postcondition in autofmt
Expand Down
25 changes: 0 additions & 25 deletions xls/dslx/tests/enumerate.x

This file was deleted.

9 changes: 0 additions & 9 deletions xls/dslx/tests/errors/error_modules_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1097,15 +1097,6 @@ def test_user_defined_parametric_type(self):
stderr,
)

def test_match_empty_range(self):
stderr = self._run(
'xls/dslx/tests/errors/match_empty_range.x',
)
self.assertIn(
'`u32:0..u32:0` from `u32:0` to `u32:0` is an empty range',
stderr,
)

def test_parametric_test_fn(self):
stderr = self._run(
'xls/dslx/tests/errors/parametric_test_fn.x',
Expand Down
21 changes: 0 additions & 21 deletions xls/dslx/tests/errors/match_empty_range.x

This file was deleted.

22 changes: 10 additions & 12 deletions xls/dslx/type_system/deduce_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -239,18 +239,6 @@ absl::Status ValidateArrayIndex(const Index& node, const Type& array_type,
// producing a `Type`.
const auto& casted_array_type = dynamic_cast<const ArrayType&>(array_type);

// Reject indexing into zero-sized arrays regardless of whether the index is
// constexpr, since out-of-bounds semantics (return last element) are
// undefined for empty arrays.

XLS_ASSIGN_OR_RETURN(int64_t concrete_size,
casted_array_type.size().GetAsInt64());
if (concrete_size == 0) {
return TypeInferenceErrorStatus(node.span(), &array_type,
"Zero-sized arrays cannot be indexed",
file_table);
}

if (!ti.IsKnownConstExpr(rhs)) {
return absl::OkStatus();
}
Expand All @@ -270,6 +258,16 @@ absl::Status ValidateArrayIndex(const Index& node, const Type& array_type,
constexpr_index),
file_table);
}

// Reject indexing into zero-sized arrays, since out-of-bounds semantics
// (return last element) are undefined for empty arrays.
XLS_ASSIGN_OR_RETURN(int64_t concrete_size,
casted_array_type.size().GetAsInt64());
if (concrete_size == 0) {
return TypeInferenceErrorStatus(node.span(), &array_type,
"Zero-sized arrays cannot be indexed",
file_table);
}
return absl::OkStatus();
}

Expand Down
4 changes: 1 addition & 3 deletions xls/dslx/type_system/typecheck_module_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,7 @@ fn main() -> u2 { p<u32:1>(u2:0) }

TEST_F(TypecheckV2Test, IndexZeroSizedArray) {
std::string_view text = R"(fn f(a: u8[0], b: u3) -> u8 { a[b] })";
EXPECT_THAT(Typecheck(text),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("Zero-sized arrays cannot be indexed")));
XLS_EXPECT_OK(Typecheck(text));
}

TEST_F(TypecheckV2Test, ZeroMacroFunctionRefIsNotValue) {
Expand Down
27 changes: 22 additions & 5 deletions xls/dslx/type_system_v2/typecheck_module_v2_array_tuple_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1727,13 +1727,30 @@ const X = foo()..(A * 2);
}

TEST(TypecheckV2Test, RangeExprEmptyRange) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like here and in other test files, we should keep empty range/array tests but change the assertions to expect success, and add a const_assert! in the DSLX that expects it to be empty.

We should also add tests for an empty range with the start being the max of the type, for both signed and unsigned, because there is some logic which normalizes exclusive ranges by converting them into inclusive with end + 1.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I restored RangeExprEmptyRange test and added two more to the same file.

XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"(
EXPECT_THAT(R"(
const A = s8:4;
const X = A..s8:4;
)"));
ASSERT_THAT(result.tm.warnings.warnings().size(), 1);
EXPECT_EQ(result.tm.warnings.warnings()[0].message,
"`A..s8:4` from `s8:4` to `s8:4` is an empty range");
const_assert!(X == []);
)",
TypecheckSucceeds(HasNodeWithType("X", "sN[8]")));
}

TEST(TypecheckV2Test, RangeExprEmptyRangeSignedMax) {
EXPECT_THAT(R"(
const A = s32::MAX;
const X = A..A;
const_assert!(X == []);
)",
TypecheckSucceeds(HasNodeWithType("X", "sN[32]")));
}

TEST(TypecheckV2Test, RangeExprEmptyRangeUnsignedMax) {
EXPECT_THAT(R"(
const A = u32::MAX;
const X = A..A;
const_assert!(X == []);
)",
TypecheckSucceeds(HasNodeWithType("X", "uN[32]")));
}

TEST(TypecheckV2Test, RangeExprSignednessMismatch) {
Expand Down
15 changes: 0 additions & 15 deletions xls/dslx/type_system_v2/typecheck_module_v2_builtin_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -659,21 +659,6 @@ const_assert!(element_count<imported::T>() == 10);
XLS_EXPECT_OK(TypecheckV2(kProgram, "main", &import_data));
}

TEST(TypecheckV2BuiltinTest, Enumerate) {
EXPECT_THAT(R"(const Y = enumerate<u16, u32:3>([u16:1, u16:2, u16:3]);)",
TypecheckSucceeds(HasNodeWithType("Y", "(uN[32], uN[16])[3]")));
}

TEST(TypecheckV2BuiltinTest, EnumerateImplicitSize) {
EXPECT_THAT(R"(const Y = enumerate<u16>([u16:1, u16:2, u16:3]);)",
TypecheckSucceeds(HasNodeWithType("Y", "(uN[32], uN[16])[3]")));
}

TEST(TypecheckV2BuiltinTest, EnumerateImplicitType) {
EXPECT_THAT(R"(const Y = enumerate([u16:1, u16:2, u16:3]);)",
TypecheckSucceeds(HasNodeWithType("Y", "(uN[32], uN[16])[3]")));
}

TEST(TypecheckV2BuiltinTest, Fail) {
EXPECT_THAT(
R"(
Expand Down
5 changes: 3 additions & 2 deletions xls/dslx/type_system_v2/typecheck_module_v2_lambda_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,13 @@ const_assert!(ARR[1] == u16:2);
TEST(TypecheckV2Test, NestedLambdas) {
EXPECT_THAT(
R"(
import std;
fn main() -> u32[4][5] {
let z = zero!<u32[4][5]>();
map(enumerate(z), | tup | {
map(std::enumerate(z), | tup | {
let i = tup.0;
let arr = tup.1;
map(enumerate(arr), | tup2 | {
map(std::enumerate(arr), | tup2 | {
let j = tup2.0;
i + j
})
Expand Down
Loading
Loading