Skip to content

Commit af9149a

Browse files
Add tool to generate intrinsics conversion automatically
1 parent 035ac03 commit af9149a

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ res
2020
test-backend
2121
gcc_path
2222
benchmarks
23+
tools/llvm-project

tools/generate_intrinsics.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import os
2+
import re
3+
import sys
4+
import subprocess
5+
from os import walk
6+
7+
8+
LLVM_PATH = llvm_path = os.path.join(
9+
os.path.dirname(os.path.abspath(__file__)),
10+
"llvm-project",
11+
)
12+
13+
def run_command(command, cwd=None):
14+
p = subprocess.Popen(command, cwd=cwd)
15+
if p.wait() != 0:
16+
print("command `{}` failed...".format(" ".join(command)))
17+
sys.exit(1)
18+
19+
20+
def clone_llvm_repository():
21+
if os.path.exists(LLVM_PATH):
22+
while True:
23+
choice = input("There is already a llvm-project folder, do you want to update it? [y/N]")
24+
if choice == "" or choice.lower() == "n":
25+
print("Skipping repository update.")
26+
return
27+
elif choice.lower() == "y":
28+
print("Updating repository...")
29+
run_command(["git", "pull", "origin"], cwd="llvm-project")
30+
return
31+
else:
32+
print("Didn't understand answer...")
33+
print("Cloning LLVM repository...")
34+
run_command(["git", "clone", "https://github.com/llvm/llvm-project", "--depth", "1", LLVM_PATH])
35+
36+
37+
def extract_instrinsics(intrinsics, file):
38+
print("Extracting intrinsics from `{}`...".format(file))
39+
with open(file, "r", encoding="utf8") as f:
40+
content = f.read()
41+
42+
lines = content.splitlines()
43+
pos = 0
44+
current_arch = None
45+
while pos < len(lines):
46+
line = lines[pos].strip()
47+
if line.startswith("let TargetPrefix ="):
48+
current_arch = line.split('"')[1].strip()
49+
if len(current_arch) == 0:
50+
current_arch = None
51+
elif current_arch is None:
52+
pass
53+
elif line == "}":
54+
current_arch = None
55+
elif line.startswith("def "):
56+
content = ""
57+
while not content.endswith(";") and pos < len(lines):
58+
line = lines[pos].split(" // ")[0].strip()
59+
content += line
60+
pos += 1
61+
entries = re.findall('GCCBuiltin<"(\\w+)">', content)
62+
if len(entries) > 0:
63+
intrinsic = content.split(":")[0].split(" ")[1].strip()
64+
intrinsic = intrinsic.split("_")
65+
if len(intrinsic) < 2 or intrinsic[0] != "int":
66+
continue
67+
intrinsic[0] = "llvm"
68+
intrinsic = ".".join(intrinsic)
69+
if current_arch not in intrinsics:
70+
intrinsics[current_arch] = []
71+
for entry in entries:
72+
intrinsics[current_arch].append('"{}" => "{}",'.format(intrinsic, entry))
73+
continue
74+
pos += 1
75+
continue
76+
print("Done!")
77+
78+
79+
def update_intrinsics():
80+
files = []
81+
intrinsics_path = os.path.join(LLVM_PATH, "llvm/include/llvm/IR")
82+
for (dirpath, dirnames, filenames) in walk(intrinsics_path):
83+
files.extend([os.path.join(intrinsics_path, f) for f in filenames if f.endswith(".td")])
84+
85+
intrinsics = {}
86+
for file in files:
87+
extract_instrinsics(intrinsics, file)
88+
89+
archs = [arch for arch in intrinsics]
90+
archs.sort()
91+
output_file = os.path.join(
92+
os.path.dirname(os.path.abspath(__file__)),
93+
"../src/intrinsic/archs.rs",
94+
)
95+
print("Updating content of `{}`...".format(output_file))
96+
with open(output_file, "w", encoding="utf8") as out:
97+
out.write("// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`\n")
98+
out.write("// DO NOT EDIT IT!\n")
99+
out.write("match name {\n")
100+
for arch in archs:
101+
if len(intrinsics[arch]) == 0:
102+
continue
103+
intrinsics[arch].sort()
104+
out.write(' // {}\n'.format(arch))
105+
out.write('\n'.join([' {}'.format(x) for x in intrinsics[arch]]))
106+
out.write('\n')
107+
out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),\n')
108+
out.write("}\n")
109+
print("Done!")
110+
111+
112+
def main():
113+
# First, we clone the LLVM repository if it's not already here.
114+
clone_llvm_repository()
115+
update_intrinsics()
116+
117+
118+
if __name__ == "__main__":
119+
sys.exit(main())

0 commit comments

Comments
 (0)