Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suppress testing SemIR in int builtin tests. #4748

Merged
merged 9 commits into from
Dec 31, 2024
10 changes: 10 additions & 0 deletions testing/file_test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ Supported comment markers are:
ARGS can be specified at most once. If not provided, the FileTestBase child
is responsible for providing default arguments.

- ```
// EXTRA-ARGS: <arguments>
```

Same as `ARGS`, including substitution behavior, but appends to the default
argument list instead of replacing it.

`EXTRA-ARGS` can be specified at most once, and a test cannot specify both
`ARGS` and `EXTRA-ARGS`.

- ```
// SET-CAPTURE-CONSOLE-OUTPUT
```
Expand Down
23 changes: 16 additions & 7 deletions testing/file_test/file_test_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ auto FileTestBase::ProcessTestFileAndRun(TestContext& context)
// Process arguments.
if (context.test_args.empty()) {
context.test_args = GetDefaultArgs();
context.test_args.append(context.extra_args);
}
CARBON_RETURN_IF_ERROR(
DoArgReplacements(context.test_args, context.test_files));
Expand Down Expand Up @@ -767,24 +768,31 @@ static auto TryConsumeCheck(
return true;
}

// Processes ARGS lines when found. Returns true if the line is consumed.
// Processes ARGS and EXTRA-ARGS lines when found. Returns true if the line is
// consumed.
static auto TryConsumeArgs(llvm::StringRef line, llvm::StringRef line_trimmed,
llvm::SmallVector<std::string>* args)
llvm::SmallVector<std::string>* args,
llvm::SmallVector<std::string>* extra_args)
-> ErrorOr<bool> {
if (!line_trimmed.consume_front("// ARGS: ")) {
llvm::SmallVector<std::string>* arg_list = nullptr;
if (line_trimmed.consume_front("// ARGS: ")) {
arg_list = args;
} else if (line_trimmed.consume_front("// EXTRA-ARGS: ")) {
arg_list = extra_args;
} else {
return false;
}

if (!args->empty()) {
return ErrorBuilder() << "ARGS was specified multiple times: "
if (!args->empty() || !extra_args->empty()) {
return ErrorBuilder() << "ARGS / EXTRA-ARGS specified multiple times: "
<< line.str();
}

// Split the line into arguments.
std::pair<llvm::StringRef, llvm::StringRef> cursor =
llvm::getToken(line_trimmed);
while (!cursor.first.empty()) {
args->push_back(std::string(cursor.first));
arg_list->push_back(std::string(cursor.first));
cursor = llvm::getToken(cursor.second);
}

Expand Down Expand Up @@ -884,7 +892,8 @@ auto FileTestBase::ProcessTestFile(TestContext& context) -> ErrorOr<Success> {
FileTestLine(split.file_index, line_index, line));

CARBON_ASSIGN_OR_RETURN(
is_consumed, TryConsumeArgs(line, line_trimmed, &context.test_args));
is_consumed, TryConsumeArgs(line, line_trimmed, &context.test_args,
&context.extra_args));
if (is_consumed) {
continue;
}
Expand Down
4 changes: 4 additions & 0 deletions testing/file_test/file_test_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ class FileTestBase : public testing::Test {
// Arguments for the test, generated from ARGS.
llvm::SmallVector<std::string> test_args;

// Extra arguments for the test, generated from EXTRA-ARGS. Unlike ARGS,
// setting EXTRA-ARGS does not suppress the default arguments.
llvm::SmallVector<std::string> extra_args;

// Files in the test, generated by content and splits.
llvm::SmallVector<TestFile> test_files;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// ARGS: compile --no-prelude-import --phase=check --dump-sem-ir --dump-raw-sem-ir %s
// EXTRA-ARGS: --dump-raw-sem-ir
//
// Check that we can combine textual IR and raw IR dumping in one compile.
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// ARGS: compile --no-prelude-import --phase=check --dump-raw-sem-ir %s
// EXTRA-ARGS: --no-dump-sem-ir --dump-raw-sem-ir
//
// Check that raw IR dumping works as expected.
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// ARGS: compile --no-prelude-import --phase=check --dump-sem-ir --dump-raw-sem-ir %s
// EXTRA-ARGS: --dump-raw-sem-ir
//
// Check that we can combine textual IR and raw IR dumping in one compile.
//
Expand Down
34 changes: 15 additions & 19 deletions toolchain/check/testdata/basics/no_prelude/raw_identifier.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// ARGS: compile --no-prelude-import --phase=check --dump-sem-ir %s
//
// Check that the command-line flag to dump textual IR works.
zygoloid marked this conversation as resolved.
Show resolved Hide resolved
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/no_prelude/raw_identifier.carbon
Expand Down Expand Up @@ -48,12 +44,12 @@ fn C(r#if: ()) -> () {
// CHECK:STDOUT: %return.patt: %empty_tuple.type = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %empty_tuple.type = out_param_pattern %return.patt, runtime_param1
// CHECK:STDOUT: } {
// CHECK:STDOUT: %.loc15_17.1: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc15_17.2: type = converted %.loc15_17.1, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %.loc11_17.1: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc11_17.2: type = converted %.loc11_17.1, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %n.param: %empty_tuple.type = value_param runtime_param0
// CHECK:STDOUT: %.loc15_10.1: type = splice_block %.loc15_10.3 [template = constants.%empty_tuple.type] {
// CHECK:STDOUT: %.loc15_10.2: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc15_10.3: type = converted %.loc15_10.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %.loc11_10.1: type = splice_block %.loc11_10.3 [template = constants.%empty_tuple.type] {
// CHECK:STDOUT: %.loc11_10.2: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc11_10.3: type = converted %.loc11_10.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: }
// CHECK:STDOUT: %n: %empty_tuple.type = bind_name n, %n.param
// CHECK:STDOUT: %return.param: ref %empty_tuple.type = out_param runtime_param1
Expand All @@ -65,12 +61,12 @@ fn C(r#if: ()) -> () {
// CHECK:STDOUT: %return.patt: %empty_tuple.type = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %empty_tuple.type = out_param_pattern %return.patt, runtime_param1
// CHECK:STDOUT: } {
// CHECK:STDOUT: %.loc19_19.1: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc19_19.2: type = converted %.loc19_19.1, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %.loc15_19.1: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc15_19.2: type = converted %.loc15_19.1, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %n.param: %empty_tuple.type = value_param runtime_param0
// CHECK:STDOUT: %.loc19_12.1: type = splice_block %.loc19_12.3 [template = constants.%empty_tuple.type] {
// CHECK:STDOUT: %.loc19_12.2: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc19_12.3: type = converted %.loc19_12.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %.loc15_12.1: type = splice_block %.loc15_12.3 [template = constants.%empty_tuple.type] {
// CHECK:STDOUT: %.loc15_12.2: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc15_12.3: type = converted %.loc15_12.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: }
// CHECK:STDOUT: %n: %empty_tuple.type = bind_name n, %n.param
// CHECK:STDOUT: %return.param: ref %empty_tuple.type = out_param runtime_param1
Expand All @@ -82,12 +78,12 @@ fn C(r#if: ()) -> () {
// CHECK:STDOUT: %return.patt: %empty_tuple.type = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %empty_tuple.type = out_param_pattern %return.patt, runtime_param1
// CHECK:STDOUT: } {
// CHECK:STDOUT: %.loc23_20.1: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc23_20.2: type = converted %.loc23_20.1, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %.loc19_20.1: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc19_20.2: type = converted %.loc19_20.1, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %if.param: %empty_tuple.type = value_param runtime_param0
// CHECK:STDOUT: %.loc23_13.1: type = splice_block %.loc23_13.3 [template = constants.%empty_tuple.type] {
// CHECK:STDOUT: %.loc23_13.2: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc23_13.3: type = converted %.loc23_13.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: %.loc19_13.1: type = splice_block %.loc19_13.3 [template = constants.%empty_tuple.type] {
// CHECK:STDOUT: %.loc19_13.2: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc19_13.3: type = converted %.loc19_13.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
// CHECK:STDOUT: }
// CHECK:STDOUT: %if: %empty_tuple.type = bind_name r#if, %if.param
// CHECK:STDOUT: %return.param: ref %empty_tuple.type = out_param runtime_param1
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/testdata/basics/no_prelude/raw_ir.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// ARGS: compile --no-prelude-import --phase=check --dump-raw-sem-ir %s
// EXTRA-ARGS: --no-dump-sem-ir --dump-raw-sem-ir
//
// Check that raw IR dumping works as expected.
//
Expand Down
4 changes: 2 additions & 2 deletions toolchain/check/testdata/basics/no_prelude/textual_ir.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// ARGS: compile --no-prelude-import --phase=check --dump-sem-ir %s
// EXTRA-ARGS: --dump-sem-ir
//
// Check that the command-line flag to dump textual IR works.
chandlerc marked this conversation as resolved.
Show resolved Hide resolved
// Check that textual IR dumping works as expected.
//
// AUTOUPDATE
// TIP: To test this file alone, run:
Expand Down
110 changes: 2 additions & 108 deletions toolchain/check/testdata/builtins/int/and.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// EXTRA-ARGS: --no-dump-sem-ir
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/and.carbon
Expand All @@ -18,111 +20,3 @@ let arr_p: [i32; 8]* = &arr;
fn RuntimeCall(a: i32, b: i32) -> i32 {
return And(a, b);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The SemIR seams still useful, and the only real test we have for the runtime call case. Would it make sense to split the runtime call tests out to files that continue to dump SemIR and only skip it in the ones where we do compile time validation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the only thing this is testing that's specific to each builtin is that a runtime call is valid. Beside that, the handling is not specific to the particular builtin -- we get the same call SemIR regardless of the kind of builtin -- so I think it's probably good enough to test that only once rather than once per builtin.

To that end, I've gone ahead and added SemIR output coverage for runtime calls to toolchain/check/testdata/function/builtin/call.carbon (which previously only covered compile-time calls).

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure... Maybe RuntimeCallIsValid or something to make that a bit more obvious why there is nothing verified beyond that?


// CHECK:STDOUT: --- int_and.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [template]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [template]
// CHECK:STDOUT: %And.type: type = fn_type @And [template]
// CHECK:STDOUT: %And: %And.type = struct_value () [template]
// CHECK:STDOUT: %int_8.2: Core.IntLiteral = int_value 8 [template]
// CHECK:STDOUT: %array_type: type = array_type %int_8.2, %i32 [template]
// CHECK:STDOUT: %ptr: type = ptr_type %array_type [template]
// CHECK:STDOUT: %RuntimeCall.type: type = fn_type @RuntimeCall [template]
// CHECK:STDOUT: %RuntimeCall: %RuntimeCall.type = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .Int = %import_ref.1
// CHECK:STDOUT: .ImplicitAs = %import_ref.5
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .And = %And.decl
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .arr_p = @__global_init.%arr_p
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %And.decl: %And.type = fn_decl @And [template = constants.%And] {
// CHECK:STDOUT: %a.patt: %i32 = binding_pattern a
// CHECK:STDOUT: %a.param_patt: %i32 = value_param_pattern %a.patt, runtime_param0
// CHECK:STDOUT: %b.patt: %i32 = binding_pattern b
// CHECK:STDOUT: %b.param_patt: %i32 = value_param_pattern %b.patt, runtime_param1
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param2
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc2_27: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc2_27: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %a.param: %i32 = value_param runtime_param0
// CHECK:STDOUT: %.loc2_11: type = splice_block %i32.loc2_11 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc2_11: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc2_11: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param
// CHECK:STDOUT: %b.param: %i32 = value_param runtime_param1
// CHECK:STDOUT: %.loc2_19: type = splice_block %i32.loc2_19 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc2_19: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc2_19: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %b: %i32 = bind_name b, %b.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param2
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %arr.var: ref %array_type = var arr
// CHECK:STDOUT: %arr: ref %array_type = bind_name arr, %arr.var
// CHECK:STDOUT: %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
// CHECK:STDOUT: %a.patt: %i32 = binding_pattern a
// CHECK:STDOUT: %a.param_patt: %i32 = value_param_pattern %a.patt, runtime_param0
// CHECK:STDOUT: %b.patt: %i32 = binding_pattern b
// CHECK:STDOUT: %b.param_patt: %i32 = value_param_pattern %b.patt, runtime_param1
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param2
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc7_35: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc7_35: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %a.param: %i32 = value_param runtime_param0
// CHECK:STDOUT: %.loc7_19: type = splice_block %i32.loc7_19 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc7_19: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc7_19: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param
// CHECK:STDOUT: %b.param: %i32 = value_param runtime_param1
// CHECK:STDOUT: %.loc7_27: type = splice_block %i32.loc7_27 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc7_27: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc7_27: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %b: %i32 = bind_name b, %b.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param2
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @And(%a.param_patt: %i32, %b.param_patt: %i32) -> %i32 = "int.and";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a.param_patt: %i32, %b.param_patt: %i32) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %And.ref: %And.type = name_ref And, file.%And.decl [template = constants.%And]
// CHECK:STDOUT: %a.ref: %i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: %i32 = name_ref b, %b
// CHECK:STDOUT: %int.and: init %i32 = call %And.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc8_19.1: %i32 = value_of_initializer %int.and
// CHECK:STDOUT: %.loc8_19.2: %i32 = converted %int.and, %.loc8_19.1
// CHECK:STDOUT: return %.loc8_19.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %arr.ref: ref %array_type = name_ref arr, file.%arr
// CHECK:STDOUT: %addr: %ptr = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: %ptr = bind_name arr_p, %addr
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
Loading
Loading