~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/generate_rust_target.rs

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /scripts/generate_rust_target.rs (Architecture i386) and /scripts/generate_rust_target.rs (Architecture ppc)


  1 // SPDX-License-Identifier: GPL-2.0                 1 // SPDX-License-Identifier: GPL-2.0
  2                                                     2 
  3 //! The custom target specification file gener      3 //! The custom target specification file generator for `rustc`.
  4 //!                                                 4 //!
  5 //! To configure a target from scratch, a JSON      5 //! To configure a target from scratch, a JSON-encoded file has to be passed
  6 //! to `rustc` (introduced in [RFC 131]). Thes      6 //! to `rustc` (introduced in [RFC 131]). These options and the file itself are
  7 //! unstable. Eventually, `rustc` should provi      7 //! unstable. Eventually, `rustc` should provide a way to do this in a stable
  8 //! manner. For instance, via command-line arg      8 //! manner. For instance, via command-line arguments. Therefore, this file
  9 //! should avoid using keys which can be set v      9 //! should avoid using keys which can be set via `-C` or `-Z` options.
 10 //!                                                10 //!
 11 //! [RFC 131]: https://rust-lang.github.io/rfc     11 //! [RFC 131]: https://rust-lang.github.io/rfcs/0131-target-specification.html
 12                                                    12 
 13 use std::{                                         13 use std::{
 14     collections::HashMap,                          14     collections::HashMap,
 15     fmt::{Display, Formatter, Result},             15     fmt::{Display, Formatter, Result},
 16     io::BufRead,                                   16     io::BufRead,
 17 };                                                 17 };
 18                                                    18 
 19 enum Value {                                       19 enum Value {
 20     Boolean(bool),                                 20     Boolean(bool),
 21     Number(i32),                                   21     Number(i32),
 22     String(String),                                22     String(String),
 23     Array(Vec<Value>),                             23     Array(Vec<Value>),
 24     Object(Object),                                24     Object(Object),
 25 }                                                  25 }
 26                                                    26 
 27 type Object = Vec<(String, Value)>;                27 type Object = Vec<(String, Value)>;
 28                                                    28 
 29 fn comma_sep<T>(                                   29 fn comma_sep<T>(
 30     seq: &[T],                                     30     seq: &[T],
 31     formatter: &mut Formatter<'_>,                 31     formatter: &mut Formatter<'_>,
 32     f: impl Fn(&mut Formatter<'_>, &T) -> Resu     32     f: impl Fn(&mut Formatter<'_>, &T) -> Result,
 33 ) -> Result {                                      33 ) -> Result {
 34     if let [ref rest @ .., ref last] = seq[..]     34     if let [ref rest @ .., ref last] = seq[..] {
 35         for v in rest {                            35         for v in rest {
 36             f(formatter, v)?;                      36             f(formatter, v)?;
 37             formatter.write_str(",")?;             37             formatter.write_str(",")?;
 38         }                                          38         }
 39         f(formatter, last)?;                       39         f(formatter, last)?;
 40     }                                              40     }
 41     Ok(())                                         41     Ok(())
 42 }                                                  42 }
 43                                                    43 
 44 /// Minimal "almost JSON" generator (e.g. no `     44 /// Minimal "almost JSON" generator (e.g. no `null`s, no escaping),
 45 /// enough for this purpose.                       45 /// enough for this purpose.
 46 impl Display for Value {                           46 impl Display for Value {
 47     fn fmt(&self, formatter: &mut Formatter<'_     47     fn fmt(&self, formatter: &mut Formatter<'_>) -> Result {
 48         match self {                               48         match self {
 49             Value::Boolean(boolean) => write!(     49             Value::Boolean(boolean) => write!(formatter, "{}", boolean),
 50             Value::Number(number) => write!(fo     50             Value::Number(number) => write!(formatter, "{}", number),
 51             Value::String(string) => write!(fo     51             Value::String(string) => write!(formatter, "\"{}\"", string),
 52             Value::Array(values) => {              52             Value::Array(values) => {
 53                 formatter.write_str("[")?;         53                 formatter.write_str("[")?;
 54                 comma_sep(&values[..], formatt     54                 comma_sep(&values[..], formatter, |formatter, v| v.fmt(formatter))?;
 55                 formatter.write_str("]")           55                 formatter.write_str("]")
 56             }                                      56             }
 57             Value::Object(object) => {             57             Value::Object(object) => {
 58                 formatter.write_str("{")?;         58                 formatter.write_str("{")?;
 59                 comma_sep(&object[..], formatt     59                 comma_sep(&object[..], formatter, |formatter, v| {
 60                     write!(formatter, "\"{}\":     60                     write!(formatter, "\"{}\": {}", v.0, v.1)
 61                 })?;                               61                 })?;
 62                 formatter.write_str("}")           62                 formatter.write_str("}")
 63             }                                      63             }
 64         }                                          64         }
 65     }                                              65     }
 66 }                                                  66 }
 67                                                    67 
 68 impl From<bool> for Value {                        68 impl From<bool> for Value {
 69     fn from(value: bool) -> Self {                 69     fn from(value: bool) -> Self {
 70         Self::Boolean(value)                       70         Self::Boolean(value)
 71     }                                              71     }
 72 }                                                  72 }
 73                                                    73 
 74 impl From<i32> for Value {                         74 impl From<i32> for Value {
 75     fn from(value: i32) -> Self {                  75     fn from(value: i32) -> Self {
 76         Self::Number(value)                        76         Self::Number(value)
 77     }                                              77     }
 78 }                                                  78 }
 79                                                    79 
 80 impl From<String> for Value {                      80 impl From<String> for Value {
 81     fn from(value: String) -> Self {               81     fn from(value: String) -> Self {
 82         Self::String(value)                        82         Self::String(value)
 83     }                                              83     }
 84 }                                                  84 }
 85                                                    85 
 86 impl From<&str> for Value {                        86 impl From<&str> for Value {
 87     fn from(value: &str) -> Self {                 87     fn from(value: &str) -> Self {
 88         Self::String(value.to_string())            88         Self::String(value.to_string())
 89     }                                              89     }
 90 }                                                  90 }
 91                                                    91 
 92 impl From<Object> for Value {                      92 impl From<Object> for Value {
 93     fn from(object: Object) -> Self {              93     fn from(object: Object) -> Self {
 94         Self::Object(object)                       94         Self::Object(object)
 95     }                                              95     }
 96 }                                                  96 }
 97                                                    97 
 98 impl<T: Into<Value>, const N: usize> From<[T;      98 impl<T: Into<Value>, const N: usize> From<[T; N]> for Value {
 99     fn from(i: [T; N]) -> Self {                   99     fn from(i: [T; N]) -> Self {
100         Self::Array(i.into_iter().map(|v| v.in    100         Self::Array(i.into_iter().map(|v| v.into()).collect())
101     }                                             101     }
102 }                                                 102 }
103                                                   103 
104 struct TargetSpec(Object);                        104 struct TargetSpec(Object);
105                                                   105 
106 impl TargetSpec {                                 106 impl TargetSpec {
107     fn new() -> TargetSpec {                      107     fn new() -> TargetSpec {
108         TargetSpec(Vec::new())                    108         TargetSpec(Vec::new())
109     }                                             109     }
110                                                   110 
111     fn push(&mut self, key: &str, value: impl     111     fn push(&mut self, key: &str, value: impl Into<Value>) {
112         self.0.push((key.to_string(), value.in    112         self.0.push((key.to_string(), value.into()));
113     }                                             113     }
114 }                                                 114 }
115                                                   115 
116 impl Display for TargetSpec {                     116 impl Display for TargetSpec {
117     fn fmt(&self, formatter: &mut Formatter<'_    117     fn fmt(&self, formatter: &mut Formatter<'_>) -> Result {
118         // We add some newlines for clarity.      118         // We add some newlines for clarity.
119         formatter.write_str("{\n")?;              119         formatter.write_str("{\n")?;
120         if let [ref rest @ .., ref last] = sel    120         if let [ref rest @ .., ref last] = self.0[..] {
121             for (key, value) in rest {            121             for (key, value) in rest {
122                 write!(formatter, "    \"{}\":    122                 write!(formatter, "    \"{}\": {},\n", key, value)?;
123             }                                     123             }
124             write!(formatter, "    \"{}\": {}\    124             write!(formatter, "    \"{}\": {}\n", last.0, last.1)?;
125         }                                         125         }
126         formatter.write_str("}")                  126         formatter.write_str("}")
127     }                                             127     }
128 }                                                 128 }
129                                                   129 
130 struct KernelConfig(HashMap<String, String>);     130 struct KernelConfig(HashMap<String, String>);
131                                                   131 
132 impl KernelConfig {                               132 impl KernelConfig {
133     /// Parses `include/config/auto.conf` from    133     /// Parses `include/config/auto.conf` from `stdin`.
134     fn from_stdin() -> KernelConfig {             134     fn from_stdin() -> KernelConfig {
135         let mut result = HashMap::new();          135         let mut result = HashMap::new();
136                                                   136 
137         let stdin = std::io::stdin();             137         let stdin = std::io::stdin();
138         let mut handle = stdin.lock();            138         let mut handle = stdin.lock();
139         let mut line = String::new();             139         let mut line = String::new();
140                                                   140 
141         loop {                                    141         loop {
142             line.clear();                         142             line.clear();
143                                                   143 
144             if handle.read_line(&mut line).unw    144             if handle.read_line(&mut line).unwrap() == 0 {
145                 break;                            145                 break;
146             }                                     146             }
147                                                   147 
148             if line.starts_with('#') {            148             if line.starts_with('#') {
149                 continue;                         149                 continue;
150             }                                     150             }
151                                                   151 
152             let (key, value) = line.split_once    152             let (key, value) = line.split_once('=').expect("Missing `=` in line.");
153             result.insert(key.to_string(), val    153             result.insert(key.to_string(), value.trim_end_matches('\n').to_string());
154         }                                         154         }
155                                                   155 
156         KernelConfig(result)                      156         KernelConfig(result)
157     }                                             157     }
158                                                   158 
159     /// Does the option exist in the configura    159     /// Does the option exist in the configuration (any value)?
160     ///                                           160     ///
161     /// The argument must be passed without th    161     /// The argument must be passed without the `CONFIG_` prefix.
162     /// This avoids repetition and it also avo    162     /// This avoids repetition and it also avoids `fixdep` making us
163     /// depend on it.                             163     /// depend on it.
164     fn has(&self, option: &str) -> bool {         164     fn has(&self, option: &str) -> bool {
165         let option = "CONFIG_".to_owned() + op    165         let option = "CONFIG_".to_owned() + option;
166         self.0.contains_key(&option)              166         self.0.contains_key(&option)
167     }                                             167     }
168 }                                                 168 }
169                                                   169 
170 fn main() {                                       170 fn main() {
171     let cfg = KernelConfig::from_stdin();         171     let cfg = KernelConfig::from_stdin();
172     let mut ts = TargetSpec::new();               172     let mut ts = TargetSpec::new();
173                                                   173 
174     // `llvm-target`s are taken from `scripts/    174     // `llvm-target`s are taken from `scripts/Makefile.clang`.
175     if cfg.has("ARM64") {                         175     if cfg.has("ARM64") {
176         panic!("arm64 uses the builtin rustc a    176         panic!("arm64 uses the builtin rustc aarch64-unknown-none target");
177     } else if cfg.has("RISCV") {                  177     } else if cfg.has("RISCV") {
178         if cfg.has("64BIT") {                     178         if cfg.has("64BIT") {
179             panic!("64-bit RISC-V uses the bui    179             panic!("64-bit RISC-V uses the builtin rustc riscv64-unknown-none-elf target");
180         } else {                                  180         } else {
181             panic!("32-bit RISC-V is an unsupp    181             panic!("32-bit RISC-V is an unsupported architecture");
182         }                                         182         }
183     } else if cfg.has("X86_64") {                 183     } else if cfg.has("X86_64") {
184         ts.push("arch", "x86_64");                184         ts.push("arch", "x86_64");
185         ts.push(                                  185         ts.push(
186             "data-layout",                        186             "data-layout",
187             "e-m:e-p270:32:32-p271:32:32-p272:    187             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
188         );                                        188         );
189         let mut features = "-mmx,+soft-float".    189         let mut features = "-mmx,+soft-float".to_string();
190         if cfg.has("MITIGATION_RETPOLINE") {      190         if cfg.has("MITIGATION_RETPOLINE") {
191             // The kernel uses `-mretpoline-ex    191             // The kernel uses `-mretpoline-external-thunk` (for Clang), which Clang maps to the
192             // target feature of the same name    192             // target feature of the same name plus the other two target features in
193             // `clang/lib/Driver/ToolChains/Ar    193             // `clang/lib/Driver/ToolChains/Arch/X86.cpp`. These should be eventually enabled via
194             // `-Ctarget-feature` when `rustc`    194             // `-Ctarget-feature` when `rustc` starts recognizing them (or via a new dedicated
195             // flag); see https://github.com/r    195             // flag); see https://github.com/rust-lang/rust/issues/116852.
196             features += ",+retpoline-external-    196             features += ",+retpoline-external-thunk";
197             features += ",+retpoline-indirect-    197             features += ",+retpoline-indirect-branches";
198             features += ",+retpoline-indirect-    198             features += ",+retpoline-indirect-calls";
199         }                                         199         }
200         if cfg.has("MITIGATION_SLS") {            200         if cfg.has("MITIGATION_SLS") {
201             // The kernel uses `-mharden-sls=a    201             // The kernel uses `-mharden-sls=all`, which Clang maps to both these target features in
202             // `clang/lib/Driver/ToolChains/Ar    202             // `clang/lib/Driver/ToolChains/Arch/X86.cpp`. These should be eventually enabled via
203             // `-Ctarget-feature` when `rustc`    203             // `-Ctarget-feature` when `rustc` starts recognizing them (or via a new dedicated
204             // flag); see https://github.com/r    204             // flag); see https://github.com/rust-lang/rust/issues/116851.
205             features += ",+harden-sls-ijmp";      205             features += ",+harden-sls-ijmp";
206             features += ",+harden-sls-ret";       206             features += ",+harden-sls-ret";
207         }                                         207         }
208         ts.push("features", features);            208         ts.push("features", features);
209         ts.push("llvm-target", "x86_64-linux-g    209         ts.push("llvm-target", "x86_64-linux-gnu");
210         ts.push("supported-sanitizers", ["kcfi    210         ts.push("supported-sanitizers", ["kcfi", "kernel-address"]);
211         ts.push("target-pointer-width", "64");    211         ts.push("target-pointer-width", "64");
212     } else if cfg.has("X86_32") {                 212     } else if cfg.has("X86_32") {
213         // This only works on UML, as i386 oth    213         // This only works on UML, as i386 otherwise needs regparm support in rustc
214         if !cfg.has("UML") {                      214         if !cfg.has("UML") {
215             panic!("32-bit x86 only works unde    215             panic!("32-bit x86 only works under UML");
216         }                                         216         }
217         ts.push("arch", "x86");                   217         ts.push("arch", "x86");
218         ts.push(                                  218         ts.push(
219             "data-layout",                        219             "data-layout",
220             "e-m:e-p:32:32-p270:32:32-p271:32:    220             "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
221         );                                        221         );
222         let mut features = "-mmx,+soft-float".    222         let mut features = "-mmx,+soft-float".to_string();
223         if cfg.has("MITIGATION_RETPOLINE") {      223         if cfg.has("MITIGATION_RETPOLINE") {
224             features += ",+retpoline-external-    224             features += ",+retpoline-external-thunk";
225         }                                         225         }
226         ts.push("features", features);            226         ts.push("features", features);
227         ts.push("llvm-target", "i386-unknown-l    227         ts.push("llvm-target", "i386-unknown-linux-gnu");
228         ts.push("target-pointer-width", "32");    228         ts.push("target-pointer-width", "32");
229     } else if cfg.has("LOONGARCH") {              229     } else if cfg.has("LOONGARCH") {
230         panic!("loongarch uses the builtin rus    230         panic!("loongarch uses the builtin rustc loongarch64-unknown-none-softfloat target");
231     } else {                                      231     } else {
232         panic!("Unsupported architecture");       232         panic!("Unsupported architecture");
233     }                                             233     }
234                                                   234 
235     ts.push("emit-debug-gdb-scripts", false);     235     ts.push("emit-debug-gdb-scripts", false);
236     ts.push("frame-pointer", "may-omit");         236     ts.push("frame-pointer", "may-omit");
237     ts.push(                                      237     ts.push(
238         "stack-probes",                           238         "stack-probes",
239         vec![("kind".to_string(), Value::Strin    239         vec![("kind".to_string(), Value::String("none".to_string()))],
240     );                                            240     );
241                                                   241 
242     // Everything else is LE, whether `CPU_LIT    242     // Everything else is LE, whether `CPU_LITTLE_ENDIAN` is declared or not
243     // (e.g. x86). It is also `rustc`'s defaul    243     // (e.g. x86). It is also `rustc`'s default.
244     if cfg.has("CPU_BIG_ENDIAN") {                244     if cfg.has("CPU_BIG_ENDIAN") {
245         ts.push("target-endian", "big");          245         ts.push("target-endian", "big");
246     }                                             246     }
247                                                   247 
248     println!("{}", ts);                           248     println!("{}", ts);
249 }                                                 249 }
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php