-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
[utils] Add script to generate elaborated IR and assembly tests #89026
Changes from 6 commits
30967cf
105063b
b9c98dc
dceadc3
a75a340
c9e4841
23affca
ad7b4cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# RUN: cp %s %t && %update_test_body %t 2>&1 | count 0 | ||
# RUN: diff -u %S/Inputs/basic.test.expected %t | ||
|
||
.ifdef GEN | ||
#--- a.txt | ||
.long 0 | ||
#--- b.txt | ||
.long 1 | ||
#--- gen | ||
cat a.txt b.txt | ||
.endif | ||
.long 0 | ||
.long 1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# RUN: cp %s %t && %update_test_body %t 2>&1 | count 0 | ||
# RUN: diff -u %S/Inputs/basic.test.expected %t | ||
|
||
.ifdef GEN | ||
#--- a.txt | ||
.long 0 | ||
#--- b.txt | ||
.long 1 | ||
#--- gen | ||
cat a.txt b.txt | ||
.endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# RUN: cp %s %t && not %update_test_body %t 2>&1 | FileCheck %s | ||
# RUN: diff -u %t %s | ||
|
||
# CHECK: stdout is empty; forgot -o - ? | ||
|
||
.ifdef GEN | ||
#--- a.txt | ||
.long 0 | ||
#--- b.txt | ||
.long 1 | ||
#--- gen | ||
true | ||
.endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# RUN: cp %s %t && not %update_test_body %t 2>&1 | FileCheck %s | ||
|
||
# CHECK: 'gen' does not exist | ||
|
||
.ifdef GEN | ||
#--- a.txt | ||
.endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# RUN: cp %s %t && not %update_test_body %t 2>&1 | FileCheck %s | ||
|
||
# CHECK: log | ||
# CHECK-NEXT: 'gen' failed | ||
|
||
.ifdef GEN | ||
#--- gen | ||
echo log >&2 | ||
false # gen fails due to sh -e | ||
true | ||
.endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import platform | ||
|
||
if platform.system() == "Windows": | ||
config.unsupported = True |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# RUN: cp %s %t && not %update_test_body %t 2>&1 | FileCheck %s | ||
|
||
# CHECK: error: -: no part separator was found | ||
|
||
.ifdef GEN | ||
true | ||
.endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
#!/usr/bin/env python3 | ||
"""Generate test body using split-file and a custom script. | ||
Currently, only assembly files are supported by placing generation instructions | ||
surrounded by .ifdef GEN/.endif directives. | ||
|
||
.ifdef GEN | ||
#--- a.cc | ||
int va; | ||
#--- gen | ||
clang --target=aarch64-linux -S -g a.cc -o - | ||
.endif | ||
# content generated by the script 'gen' | ||
|
||
The script will prepare extra files with `split-file`, invoke `gen`, and then | ||
rewrite the part after `.endif` with its stdout. | ||
|
||
Example: | ||
PATH=/path/to/clang_build/bin:$PATH llvm/utils/update_test_body.py path/to/test.s | ||
""" | ||
import argparse | ||
import contextlib | ||
import os | ||
import subprocess | ||
import sys | ||
import tempfile | ||
|
||
|
||
@contextlib.contextmanager | ||
def cd(directory): | ||
cwd = os.getcwd() | ||
os.chdir(directory) | ||
try: | ||
yield | ||
finally: | ||
os.chdir(cwd) | ||
|
||
|
||
def process(args, path): | ||
split_file_input = [] | ||
prolog = [] | ||
is_split_file_input = False | ||
is_prolog = True | ||
with open(path) as f: | ||
for line in f.readlines(): | ||
line = line.rstrip() | ||
if is_prolog: | ||
prolog.append(line) | ||
if line.startswith(".endif"): | ||
is_split_file_input = is_prolog = False | ||
if is_split_file_input: | ||
split_file_input.append(line) | ||
if line.startswith(".ifdef GEN"): | ||
is_split_file_input = True | ||
|
||
if not split_file_input: | ||
print("no .ifdef GEN", file=sys.stderr) | ||
return 1 | ||
if is_split_file_input: | ||
print("no .endif", file=sys.stderr) | ||
return 1 | ||
with tempfile.TemporaryDirectory(prefix="update_test_body_") as dir: | ||
try: | ||
sub = subprocess.run( | ||
["split-file", "-", dir], | ||
input="\n".join(split_file_input).encode(), | ||
capture_output=True, | ||
check=True, | ||
) | ||
except subprocess.CalledProcessError as ex: | ||
sys.stderr.write(ex.stderr.decode()) | ||
return 1 | ||
with cd(dir): | ||
if args.shell: | ||
print(f"invoke shell in the temporary directory '{dir}'") | ||
subprocess.run([os.environ.get("SHELL", "sh")]) | ||
return 0 | ||
if not os.path.exists("gen"): | ||
print("'gen' does not exist", file=sys.stderr) | ||
return 1 | ||
|
||
sub = subprocess.run( | ||
["sh", "-eu", "gen"], | ||
capture_output=True, | ||
# Don't encode the directory information to the Clang output. | ||
# Remove unneeded details (.ident) as well. | ||
env=dict( | ||
os.environ, | ||
CCC_OVERRIDE_OPTIONS="#^-fno-ident", | ||
PWD="/proc/self/cwd", | ||
), | ||
) | ||
sys.stderr.write(sub.stderr.decode()) | ||
if sub.returncode != 0: | ||
print("'gen' failed", file=sys.stderr) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a weird mixture of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I must admit that I rarely, if ever use |
||
return sub.returncode | ||
if not sub.stdout: | ||
print("stdout is empty; forgot -o - ?", file=sys.stderr) | ||
return 1 | ||
content = sub.stdout.decode() | ||
|
||
with open(path, "w") as f: | ||
# Print lines up to '.endif'. | ||
print("\n".join(prolog), file=f) | ||
# Then print the stdout of 'gen'. | ||
f.write(content) | ||
|
||
|
||
parser = argparse.ArgumentParser( | ||
description="Generate test body using split-file and a custom script" | ||
) | ||
parser.add_argument("files", nargs="+") | ||
parser.add_argument( | ||
"--shell", action="store_true", help="invoke shell instead of 'gen'" | ||
) | ||
args = parser.parse_args() | ||
for path in args.files: | ||
retcode = process(args, path) | ||
if retcode != 0: | ||
sys.exit(retcode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow this.
At least for split dwarf when generating assembly files for BOLT it helps to set -fdebug-compilation-dir= to '.' and then run bolt from a test directory where executable is created. That way it can find the .dwo files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've clarified this.
Clang commands don't need
-fdebug-compilation-dir=
since its default value isPWD
.