1+ import json
12import os
23import re
34import 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+
3843def 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
128211if __name__ == "__main__" :
0 commit comments