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