Skip to content

Commit 19d8617

Browse files
Generate intrinsics translations from llvmint as well
1 parent ed0ba31 commit 19d8617

File tree

2 files changed

+91
-7
lines changed

2 files changed

+91
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ test-backend
2121
gcc_path
2222
benchmarks
2323
tools/llvm-project
24+
tools/llvmint

tools/generate_intrinsics.py

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import os
23
import re
34
import sys
@@ -35,6 +36,10 @@ def clone_repository(repo_name, path, repo_url, sub_path=None):
3536
run_command(["git", "checkout"], cwd=path)
3637

3738

39+
def append_intrinsic(array, intrinsic_name, translation):
40+
array.append((intrinsic_name, translation))
41+
42+
3843
def extract_instrinsics(intrinsics, file):
3944
print("Extracting intrinsics from `{}`...".format(file))
4045
with open(file, "r", encoding="utf8") as f:
@@ -70,25 +75,85 @@ def extract_instrinsics(intrinsics, file):
7075
if current_arch not in intrinsics:
7176
intrinsics[current_arch] = []
7277
for entry in entries:
73-
intrinsics[current_arch].append('"{}" => "{}",'.format(intrinsic, entry))
78+
append_intrinsic(intrinsics[current_arch], intrinsic, entry)
7479
continue
7580
pos += 1
7681
continue
7782
print("Done!")
7883

7984

80-
def update_intrinsics(llvm_path):
85+
def extract_instrinsics_from_llvm(llvm_path, intrinsics):
8186
files = []
8287
intrinsics_path = os.path.join(llvm_path, "llvm/include/llvm/IR")
8388
for (dirpath, dirnames, filenames) in walk(intrinsics_path):
8489
files.extend([os.path.join(intrinsics_path, f) for f in filenames if f.endswith(".td")])
8590

86-
intrinsics = {}
8791
for file in files:
8892
extract_instrinsics(intrinsics, file)
8993

94+
95+
def append_translation(json_data, p, array):
96+
it = json_data["index"][p]
97+
content = it["docs"].split('`')
98+
if len(content) != 5:
99+
return
100+
append_intrinsic(array, content[1], content[3])
101+
102+
103+
def extract_instrinsics_from_llvmint(llvmint, intrinsics):
104+
archs = [
105+
"AMDGPU",
106+
"aarch64",
107+
"arm",
108+
"cuda",
109+
"hexagon",
110+
"mips",
111+
"nvvm",
112+
"ppc",
113+
"ptx",
114+
"x86",
115+
"xcore",
116+
]
117+
118+
json_file = os.path.join(llvmint, "target/doc/llvmint.json")
119+
if not os.path.exists(json_file):
120+
# We need to regenerate the documentation!
121+
run_command(
122+
["cargo", "rustdoc", "--", "-Zunstable-options", "--output-format", "json"],
123+
cwd=llvmint,
124+
)
125+
with open(json_file, "r", encoding="utf8") as f:
126+
json_data = json.loads(f.read())
127+
for p in json_data["paths"]:
128+
it = json_data["paths"][p]
129+
if it["crate_id"] != 0:
130+
# This is from an external crate.
131+
continue
132+
if it["kind"] != "function":
133+
# We're only looking for functions.
134+
continue
135+
# if len(it["path"]) == 2:
136+
# # This is a "general" intrinsic, not bound to a specific arch.
137+
# append_translation(json_data, p, general)
138+
# continue
139+
if len(it["path"]) != 3 or it["path"][1] not in archs:
140+
continue
141+
arch = it["path"][1]
142+
if arch not in intrinsics:
143+
intrinsics[arch] = []
144+
append_translation(json_data, p, intrinsics[arch])
145+
146+
147+
def update_intrinsics(llvm_path, llvmint):
148+
intrinsics = {}
149+
all_intrinsics = {}
150+
151+
extract_instrinsics_from_llvm(llvm_path, intrinsics)
152+
extract_instrinsics_from_llvmint(llvmint, intrinsics)
153+
90154
archs = [arch for arch in intrinsics]
91155
archs.sort()
156+
92157
output_file = os.path.join(
93158
os.path.dirname(os.path.abspath(__file__)),
94159
"../src/intrinsic/archs.rs",
@@ -103,8 +168,16 @@ def update_intrinsics(llvm_path):
103168
continue
104169
intrinsics[arch].sort()
105170
out.write(' // {}\n'.format(arch))
106-
out.write('\n'.join([' {}'.format(x) for x in intrinsics[arch]]))
107-
out.write('\n')
171+
for entry in intrinsics[arch]:
172+
if entry[0] in all_intrinsics:
173+
if all_intrinsics[entry[0]] == entry[1]:
174+
# This is a "full" duplicate, both the LLVM instruction and the GCC
175+
# translation are the same.
176+
continue
177+
out.write(' // [DUPLICATE]: "{}" => "{}",\n'.format(entry[0], entry[1]))
178+
else:
179+
out.write(' "{}" => "{}",\n'.format(entry[0], entry[1]))
180+
all_intrinsics[entry[0]] = entry[1]
108181
out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),\n')
109182
out.write("}\n")
110183
print("Done!")
@@ -115,14 +188,24 @@ def main():
115188
os.path.dirname(os.path.abspath(__file__)),
116189
"llvm-project",
117190
)
191+
llvmint_path = os.path.join(
192+
os.path.dirname(os.path.abspath(__file__)),
193+
"llvmint",
194+
)
118195

119196
# First, we clone the LLVM repository if it's not already here.
120197
clone_repository(
121198
"llvm-project",
122199
llvm_path,
123200
"https://github.com/llvm/llvm-project",
124-
sub_path="llvm/include/llvm/IR")
125-
update_intrinsics(llvm_path)
201+
sub_path="llvm/include/llvm/IR",
202+
)
203+
clone_repository(
204+
"llvmint",
205+
llvmint_path,
206+
"https://github.com/GuillaumeGomez/llvmint",
207+
)
208+
update_intrinsics(llvm_path, llvmint_path)
126209

127210

128211
if __name__ == "__main__":

0 commit comments

Comments
 (0)