Run non-filechecked commands in update_cc_test_checks.py
authorGiorgis Georgakoudis <georgakoudis1@llnl.gov>
Fri, 19 Feb 2021 18:45:40 +0000 (10:45 -0800)
committerGiorgis Georgakoudis <georgakoudis1@llnl.gov>
Mon, 8 Mar 2021 15:18:01 +0000 (07:18 -0800)
Some tests in clang require running non-filechecked commands to generate the actual filecheck input. For example, tests for openmp offloading require generating the host bc without any checking, before running the clang command to actually generate the filechecked IR of the target device. This patch enables `update_cc_test_checks.py` to run non-filechecked run lines in-place.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D97068

clang/test/utils/update_cc_test_checks/Inputs/exec-all-runlines.c [new file with mode: 0644]
clang/test/utils/update_cc_test_checks/Inputs/exec-all-runlines.c.expected [new file with mode: 0644]
clang/test/utils/update_cc_test_checks/exec-all-runlines.test [new file with mode: 0644]
llvm/utils/update_cc_test_checks.py

diff --git a/clang/test/utils/update_cc_test_checks/Inputs/exec-all-runlines.c b/clang/test/utils/update_cc_test_checks/Inputs/exec-all-runlines.c
new file mode 100644 (file)
index 0000000..bf18179
--- /dev/null
@@ -0,0 +1,10 @@
+// Check that the non-clang/non-filechecked runlines execute
+// RUN: cp %s %s.copy.c
+// RUN: %clang_cc1 -fopenmp %s.copy.c -emit-llvm-bc -o %t-host.bc
+// RUN: %clang_cc1 -fopenmp -fopenmp-host-ir-file-path %t-host.bc %s.copy.c -emit-llvm -o - | FileCheck %s
+
+void use(int);
+
+void test(int a)
+{
+}
diff --git a/clang/test/utils/update_cc_test_checks/Inputs/exec-all-runlines.c.expected b/clang/test/utils/update_cc_test_checks/Inputs/exec-all-runlines.c.expected
new file mode 100644 (file)
index 0000000..ffc8caa
--- /dev/null
@@ -0,0 +1,17 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// Check that the non-clang/non-filechecked runlines execute
+// RUN: cp %s %s.copy.c
+// RUN: %clang_cc1 -fopenmp %s.copy.c -emit-llvm-bc -o %t-host.bc
+// RUN: %clang_cc1 -fopenmp -fopenmp-host-ir-file-path %t-host.bc %s.copy.c -emit-llvm -o - | FileCheck %s
+
+void use(int);
+
+// CHECK-LABEL: @test(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
+// CHECK-NEXT:    ret void
+//
+void test(int a)
+{
+}
diff --git a/clang/test/utils/update_cc_test_checks/exec-all-runlines.test b/clang/test/utils/update_cc_test_checks/exec-all-runlines.test
new file mode 100644 (file)
index 0000000..caf3993
--- /dev/null
@@ -0,0 +1,8 @@
+## Test that non-clang/non-filechecked runlines execute
+
+# RUN: cp %S/Inputs/exec-all-runlines.c %t-generated.c && %update_cc_test_checks %t-generated.c
+# RUN: diff -u %S/Inputs/exec-all-runlines.c.expected %t-generated.c
+
+## Check that re-running update_cc_test_checks doesn't change the output
+# RUN: %update_cc_test_checks %t-generated.c
+# RUN: diff -u %S/Inputs/exec-all-runlines.c.expected %t-generated.c
index e5ca915..d084bc6 100755 (executable)
@@ -203,6 +203,14 @@ def get_function_body(builder, args, filename, clang_args, extra_commands,
           'are discouraged in Clang testsuite.', file=sys.stderr)
     sys.exit(1)
 
+def exec_run_line(exe):
+  popen = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+  stdout, stderr = popen.communicate()
+  if popen.returncode != 0:
+    sys.stderr.write('Failed to run ' + ' '.join(exe) + '\n')
+    sys.stderr.write(stderr)
+    sys.stderr.write(stdout)
+    sys.exit(3)
 
 def main():
   initial_args, parser = config()
@@ -221,25 +229,31 @@ def main():
       if m:
         triple_in_cmd = m.groups()[0]
 
-      # Apply %clang substitution rule, replace %s by `filename`, and append args.clang_args
-      clang_args = shlex.split(commands[0])
-      if clang_args[0] not in SUBST:
-        print('WARNING: Skipping non-clang RUN line: ' + l, file=sys.stderr)
+      # Parse executable args.
+      exec_args = shlex.split(commands[0])
+      # Execute non-clang runline.
+      if exec_args[0] not in SUBST:
+        print('NOTE: Executing non-clang RUN line: ' + l, file=sys.stderr)
+        # Replace %s by `filename`.
+        exec_args = [i.replace('%s', ti.path) if '%s' in i else i for i in exec_args]
+        exec_run_line(exec_args)
         continue
+      # This is a clang runline, apply %clang substitution rule, replace %s by `filename`,
+      # and append args.clang_args
+      clang_args = exec_args
       clang_args[0:1] = SUBST[clang_args[0]]
-      clang_args = [ti.path if i == '%s' else i for i in clang_args] + ti.args.clang_args
-
-      # Permit piping the output through opt
-      if not (len(commands) == 2 or
-              (len(commands) == 3 and commands[1].startswith('opt'))):
-        print('WARNING: Skipping non-clang RUN line: ' + l, file=sys.stderr)
+      clang_args = [i.replace('%s', ti.path) if '%s' in i else i for i in clang_args] + ti.args.clang_args
 
       # Extract -check-prefix in FileCheck args
       filecheck_cmd = commands[-1]
       common.verify_filecheck_prefixes(filecheck_cmd)
       if not filecheck_cmd.startswith('FileCheck '):
-        print('WARNING: Skipping non-FileChecked RUN line: ' + l, file=sys.stderr)
+        print('NOTE: Executing non-FileChecked clang RUN line: ' + l, file=sys.stderr)
+        # Execute non-filechecked clang runline.
+        exe = [ti.args.clang] + clang_args
+        exec_run_line(exe)
         continue
+
       check_prefixes = [item for m in common.CHECK_PREFIX_RE.finditer(filecheck_cmd)
                                for item in m.group(1).split(',')]
       if not check_prefixes: