run_make_support/external_deps/
llvm.rs

1use std::path::{Path, PathBuf};
2
3use crate::command::Command;
4use crate::env::env_var;
5
6/// Construct a new `llvm-readobj` invocation with the `GNU` output style.
7/// This assumes that `llvm-readobj` is available at `$LLVM_BIN_DIR/llvm-readobj`.
8#[track_caller]
9pub fn llvm_readobj() -> LlvmReadobj {
10    LlvmReadobj::new()
11}
12
13/// Construct a new `llvm-profdata` invocation. This assumes that `llvm-profdata` is available
14/// at `$LLVM_BIN_DIR/llvm-profdata`.
15#[track_caller]
16pub fn llvm_profdata() -> LlvmProfdata {
17    LlvmProfdata::new()
18}
19
20/// Construct a new `llvm-filecheck` invocation. This assumes that `llvm-filecheck` is available
21/// at `$LLVM_FILECHECK`.
22#[track_caller]
23pub fn llvm_filecheck() -> LlvmFilecheck {
24    LlvmFilecheck::new()
25}
26
27/// Construct a new `llvm-objdump` invocation. This assumes that `llvm-objdump` is available
28/// at `$LLVM_BIN_DIR/llvm-objdump`.
29pub fn llvm_objdump() -> LlvmObjdump {
30    LlvmObjdump::new()
31}
32
33/// Construct a new `llvm-ar` invocation. This assumes that `llvm-ar` is available
34/// at `$LLVM_BIN_DIR/llvm-ar`.
35pub fn llvm_ar() -> LlvmAr {
36    LlvmAr::new()
37}
38
39/// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
40/// at `$LLVM_BIN_DIR/llvm-nm`.
41pub fn llvm_nm() -> LlvmNm {
42    LlvmNm::new()
43}
44
45/// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
46/// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
47pub fn llvm_bcanalyzer() -> LlvmBcanalyzer {
48    LlvmBcanalyzer::new()
49}
50
51/// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available
52/// at `$LLVM_BIN_DIR/llvm-dwarfdump`.
53pub fn llvm_dwarfdump() -> LlvmDwarfdump {
54    LlvmDwarfdump::new()
55}
56
57/// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available
58/// at `$LLVM_BIN_DIR/llvm-pdbutil`.
59pub fn llvm_pdbutil() -> LlvmPdbutil {
60    LlvmPdbutil::new()
61}
62
63/// Construct a new `llvm-as` invocation. This assumes that `llvm-as` is available
64/// at `$LLVM_BIN_DIR/llvm-as`.
65pub fn llvm_as() -> LlvmAs {
66    LlvmAs::new()
67}
68
69/// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available
70/// at `$LLVM_BIN_DIR/llvm-dis`.
71pub fn llvm_dis() -> LlvmDis {
72    LlvmDis::new()
73}
74
75/// Construct a new `llvm-objcopy` invocation. This assumes that `llvm-objcopy` is available
76/// at `$LLVM_BIN_DIR/llvm-objcopy`.
77pub fn llvm_objcopy() -> LlvmObjcopy {
78    LlvmObjcopy::new()
79}
80
81/// A `llvm-readobj` invocation builder.
82#[derive(Debug)]
83#[must_use]
84pub struct LlvmReadobj {
85    cmd: Command,
86}
87
88/// A `llvm-profdata` invocation builder.
89#[derive(Debug)]
90#[must_use]
91pub struct LlvmProfdata {
92    cmd: Command,
93}
94
95/// A `llvm-filecheck` invocation builder.
96#[derive(Debug)]
97#[must_use]
98pub struct LlvmFilecheck {
99    cmd: Command,
100}
101
102/// A `llvm-objdump` invocation builder.
103#[derive(Debug)]
104#[must_use]
105pub struct LlvmObjdump {
106    cmd: Command,
107}
108
109/// A `llvm-ar` invocation builder.
110#[derive(Debug)]
111#[must_use]
112pub struct LlvmAr {
113    cmd: Command,
114}
115
116/// A `llvm-nm` invocation builder.
117#[derive(Debug)]
118#[must_use]
119pub struct LlvmNm {
120    cmd: Command,
121}
122
123/// A `llvm-bcanalyzer` invocation builder.
124#[derive(Debug)]
125#[must_use]
126pub struct LlvmBcanalyzer {
127    cmd: Command,
128}
129
130/// A `llvm-dwarfdump` invocation builder.
131#[derive(Debug)]
132#[must_use]
133pub struct LlvmDwarfdump {
134    cmd: Command,
135}
136
137/// A `llvm-pdbutil` invocation builder.
138#[derive(Debug)]
139#[must_use]
140pub struct LlvmPdbutil {
141    cmd: Command,
142}
143
144/// A `llvm-as` invocation builder.
145#[derive(Debug)]
146#[must_use]
147pub struct LlvmAs {
148    cmd: Command,
149}
150
151/// A `llvm-dis` invocation builder.
152#[derive(Debug)]
153#[must_use]
154pub struct LlvmDis {
155    cmd: Command,
156}
157
158/// A `llvm-objcopy` invocation builder.
159#[derive(Debug)]
160#[must_use]
161pub struct LlvmObjcopy {
162    cmd: Command,
163}
164
165crate::macros::impl_common_helpers!(LlvmReadobj);
166crate::macros::impl_common_helpers!(LlvmProfdata);
167crate::macros::impl_common_helpers!(LlvmFilecheck);
168crate::macros::impl_common_helpers!(LlvmObjdump);
169crate::macros::impl_common_helpers!(LlvmAr);
170crate::macros::impl_common_helpers!(LlvmNm);
171crate::macros::impl_common_helpers!(LlvmBcanalyzer);
172crate::macros::impl_common_helpers!(LlvmDwarfdump);
173crate::macros::impl_common_helpers!(LlvmPdbutil);
174crate::macros::impl_common_helpers!(LlvmAs);
175crate::macros::impl_common_helpers!(LlvmDis);
176crate::macros::impl_common_helpers!(LlvmObjcopy);
177
178/// Generate the path to the bin directory of LLVM.
179#[must_use]
180pub fn llvm_bin_dir() -> PathBuf {
181    let llvm_bin_dir = env_var("LLVM_BIN_DIR");
182    PathBuf::from(llvm_bin_dir)
183}
184
185impl LlvmReadobj {
186    /// Construct a new `llvm-readobj` invocation with the `GNU` output style.
187    /// This assumes that `llvm-readobj` is available at `$LLVM_BIN_DIR/llvm-readobj`.
188    #[track_caller]
189    pub fn new() -> Self {
190        let llvm_readobj = llvm_bin_dir().join("llvm-readobj");
191        let cmd = Command::new(llvm_readobj);
192        let mut readobj = Self { cmd };
193        readobj.elf_output_style("GNU");
194        readobj
195    }
196
197    /// Specify the format of the ELF information.
198    ///
199    /// Valid options are `LLVM` (default), `GNU`, and `JSON`.
200    pub fn elf_output_style(&mut self, style: &str) -> &mut Self {
201        self.cmd.arg("--elf-output-style");
202        self.cmd.arg(style);
203        self
204    }
205
206    /// Provide an input file.
207    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
208        self.cmd.arg(path.as_ref());
209        self
210    }
211
212    /// Pass `--file-header` to display file headers.
213    pub fn file_header(&mut self) -> &mut Self {
214        self.cmd.arg("--file-header");
215        self
216    }
217
218    /// Pass `--program-headers` to display program headers.
219    pub fn program_headers(&mut self) -> &mut Self {
220        self.cmd.arg("--program-headers");
221        self
222    }
223
224    /// Pass `--symbols` to display the symbol table, including both local
225    /// and global symbols.
226    pub fn symbols(&mut self) -> &mut Self {
227        self.cmd.arg("--symbols");
228        self
229    }
230
231    /// Pass `--dynamic-table` to display the dynamic symbol table.
232    pub fn dynamic_table(&mut self) -> &mut Self {
233        self.cmd.arg("--dynamic-table");
234        self
235    }
236
237    /// Specify the section to display.
238    pub fn section(&mut self, section: &str) -> &mut Self {
239        self.cmd.arg("--string-dump");
240        self.cmd.arg(section);
241        self
242    }
243}
244
245impl LlvmProfdata {
246    /// Construct a new `llvm-profdata` invocation. This assumes that `llvm-profdata` is available
247    /// at `$LLVM_BIN_DIR/llvm-profdata`.
248    #[track_caller]
249    pub fn new() -> Self {
250        let llvm_profdata = llvm_bin_dir().join("llvm-profdata");
251        let cmd = Command::new(llvm_profdata);
252        Self { cmd }
253    }
254
255    /// Provide an input file.
256    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
257        self.cmd.arg(path.as_ref());
258        self
259    }
260
261    /// Specify the output file path.
262    pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
263        self.cmd.arg("-o");
264        self.cmd.arg(path.as_ref());
265        self
266    }
267
268    /// Take several profile data files generated by PGO instrumentation and merge them
269    /// together into a single indexed profile data file.
270    pub fn merge(&mut self) -> &mut Self {
271        self.cmd.arg("merge");
272        self
273    }
274}
275
276impl LlvmFilecheck {
277    /// Construct a new `llvm-filecheck` invocation. This assumes that `llvm-filecheck` is available
278    /// at `$LLVM_FILECHECK`.
279    #[track_caller]
280    pub fn new() -> Self {
281        let llvm_filecheck = env_var("LLVM_FILECHECK");
282        let cmd = Command::new(llvm_filecheck);
283        Self { cmd }
284    }
285
286    /// Provide a buffer representing standard input containing patterns that will be matched
287    /// against the `.patterns(path)` call.
288    pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
289        self.cmd.stdin_buf(input);
290        self
291    }
292
293    /// Provide the patterns that need to be matched.
294    pub fn patterns<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
295        self.cmd.arg(path.as_ref());
296        self
297    }
298
299    /// `--input-file` option.
300    pub fn input_file<P: AsRef<Path>>(&mut self, input_file: P) -> &mut Self {
301        self.cmd.arg("--input-file");
302        self.cmd.arg(input_file.as_ref());
303        self
304    }
305}
306
307impl LlvmObjdump {
308    /// Construct a new `llvm-objdump` invocation. This assumes that `llvm-objdump` is available
309    /// at `$LLVM_BIN_DIR/llvm-objdump`.
310    pub fn new() -> Self {
311        let llvm_objdump = llvm_bin_dir().join("llvm-objdump");
312        let cmd = Command::new(llvm_objdump);
313        Self { cmd }
314    }
315
316    /// Provide an input file.
317    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
318        self.cmd.arg(path.as_ref());
319        self
320    }
321
322    /// Disassemble all executable sections found in the input files.
323    pub fn disassemble(&mut self) -> &mut Self {
324        self.cmd.arg("-d");
325        self
326    }
327}
328
329impl LlvmAr {
330    /// Construct a new `llvm-ar` invocation. This assumes that `llvm-ar` is available
331    /// at `$LLVM_BIN_DIR/llvm-ar`.
332    pub fn new() -> Self {
333        let llvm_ar = llvm_bin_dir().join("llvm-ar");
334        let cmd = Command::new(llvm_ar);
335        Self { cmd }
336    }
337
338    /// Automatically pass the commonly used arguments `rcus`, used for combining one or more
339    /// input object files into one output static library file.
340    pub fn obj_to_ar(&mut self) -> &mut Self {
341        self.cmd.arg("rcus");
342        self
343    }
344
345    /// Like `obj_to_ar` except creating a thin archive.
346    pub fn obj_to_thin_ar(&mut self) -> &mut Self {
347        self.cmd.arg("rcus").arg("--thin");
348        self
349    }
350
351    /// Extract archive members back to files.
352    pub fn extract(&mut self) -> &mut Self {
353        self.cmd.arg("x");
354        self
355    }
356
357    /// Print the table of contents.
358    pub fn table_of_contents(&mut self) -> &mut Self {
359        self.cmd.arg("t");
360        self
361    }
362
363    /// Provide an output, then an input file. Bundled in one function, as llvm-ar has
364    /// no "--output"-style flag.
365    pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {
366        self.cmd.arg(out.as_ref());
367        self.cmd.arg(input.as_ref());
368        self
369    }
370}
371
372impl LlvmNm {
373    /// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
374    /// at `$LLVM_BIN_DIR/llvm-nm`.
375    pub fn new() -> Self {
376        let llvm_nm = llvm_bin_dir().join("llvm-nm");
377        let cmd = Command::new(llvm_nm);
378        Self { cmd }
379    }
380
381    /// Provide an input file.
382    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
383        self.cmd.arg(path.as_ref());
384        self
385    }
386}
387
388impl LlvmBcanalyzer {
389    /// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
390    /// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
391    pub fn new() -> Self {
392        let llvm_bcanalyzer = llvm_bin_dir().join("llvm-bcanalyzer");
393        let cmd = Command::new(llvm_bcanalyzer);
394        Self { cmd }
395    }
396
397    /// Provide an input file.
398    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
399        self.cmd.arg(path.as_ref());
400        self
401    }
402}
403
404impl LlvmDwarfdump {
405    /// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available
406    /// at `$LLVM_BIN_DIR/llvm-dwarfdump`.
407    pub fn new() -> Self {
408        let llvm_dwarfdump = llvm_bin_dir().join("llvm-dwarfdump");
409        let cmd = Command::new(llvm_dwarfdump);
410        Self { cmd }
411    }
412
413    /// Provide an input file.
414    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
415        self.cmd.arg(path.as_ref());
416        self
417    }
418}
419
420impl LlvmPdbutil {
421    /// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available
422    /// at `$LLVM_BIN_DIR/llvm-pdbutil`.
423    pub fn new() -> Self {
424        let llvm_pdbutil = llvm_bin_dir().join("llvm-pdbutil");
425        let cmd = Command::new(llvm_pdbutil);
426        Self { cmd }
427    }
428
429    /// Provide an input file.
430    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
431        self.cmd.arg(path.as_ref());
432        self
433    }
434}
435
436impl LlvmObjcopy {
437    /// Construct a new `llvm-objcopy` invocation. This assumes that `llvm-objcopy` is available
438    /// at `$LLVM_BIN_DIR/llvm-objcopy`.
439    pub fn new() -> Self {
440        let llvm_objcopy = llvm_bin_dir().join("llvm-objcopy");
441        let cmd = Command::new(llvm_objcopy);
442        Self { cmd }
443    }
444
445    /// Dump the contents of `section` into the file at `path`.
446    #[track_caller]
447    pub fn dump_section<S: AsRef<str>, P: AsRef<Path>>(
448        &mut self,
449        section_name: S,
450        path: P,
451    ) -> &mut Self {
452        self.cmd.arg("--dump-section");
453        self.cmd.arg(format!("{}={}", section_name.as_ref(), path.as_ref().to_str().unwrap()));
454        self
455    }
456}
457
458impl LlvmAs {
459    /// Construct a new `llvm-as` invocation. This assumes that `llvm-as` is available
460    /// at `$LLVM_BIN_DIR/llvm-as`.
461    pub fn new() -> Self {
462        let llvm_as = llvm_bin_dir().join("llvm-as");
463        let cmd = Command::new(llvm_as);
464        Self { cmd }
465    }
466
467    /// Provide an input file.
468    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
469        self.cmd.arg(path.as_ref());
470        self
471    }
472}
473
474impl LlvmDis {
475    /// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available
476    /// at `$LLVM_BIN_DIR/llvm-dis`.
477    pub fn new() -> Self {
478        let llvm_dis = llvm_bin_dir().join("llvm-dis");
479        let cmd = Command::new(llvm_dis);
480        Self { cmd }
481    }
482
483    /// Provide an input file.
484    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
485        self.cmd.arg(path.as_ref());
486        self
487    }
488}