@@ -211,6 +211,102 @@ pub enum TargetDataLayoutErrors<'a> {
211211}
212212
213213impl TargetDataLayout {
214+ /// Parse data layout from an [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout)
215+ ///
216+ /// This function doesn't fill `c_enum_min_size` and it will always be `I32` since it can not be
217+ /// determined from llvm string.
218+ pub fn parse_from_llvm_datalayout_string < ' a > (
219+ input : & ' a str ,
220+ ) -> Result < TargetDataLayout , TargetDataLayoutErrors < ' a > > {
221+ // Parse an address space index from a string.
222+ let parse_address_space = |s : & ' a str , cause : & ' a str | {
223+ s. parse :: < u32 > ( ) . map ( AddressSpace ) . map_err ( |err| {
224+ TargetDataLayoutErrors :: InvalidAddressSpace { addr_space : s, cause, err }
225+ } )
226+ } ;
227+
228+ // Parse a bit count from a string.
229+ let parse_bits = |s : & ' a str , kind : & ' a str , cause : & ' a str | {
230+ s. parse :: < u64 > ( ) . map_err ( |err| TargetDataLayoutErrors :: InvalidBits {
231+ kind,
232+ bit : s,
233+ cause,
234+ err,
235+ } )
236+ } ;
237+
238+ // Parse a size string.
239+ let size = |s : & ' a str , cause : & ' a str | parse_bits ( s, "size" , cause) . map ( Size :: from_bits) ;
240+
241+ // Parse an alignment string.
242+ let align = |s : & [ & ' a str ] , cause : & ' a str | {
243+ if s. is_empty ( ) {
244+ return Err ( TargetDataLayoutErrors :: MissingAlignment { cause } ) ;
245+ }
246+ let align_from_bits = |bits| {
247+ Align :: from_bits ( bits)
248+ . map_err ( |err| TargetDataLayoutErrors :: InvalidAlignment { cause, err } )
249+ } ;
250+ let abi = parse_bits ( s[ 0 ] , "alignment" , cause) ?;
251+ let pref = s. get ( 1 ) . map_or ( Ok ( abi) , |pref| parse_bits ( pref, "alignment" , cause) ) ?;
252+ Ok ( AbiAndPrefAlign { abi : align_from_bits ( abi) ?, pref : align_from_bits ( pref) ? } )
253+ } ;
254+
255+ let mut dl = TargetDataLayout :: default ( ) ;
256+ let mut i128_align_src = 64 ;
257+ for spec in input. split ( '-' ) {
258+ let spec_parts = spec. split ( ':' ) . collect :: < Vec < _ > > ( ) ;
259+
260+ match & * spec_parts {
261+ [ "e" ] => dl. endian = Endian :: Little ,
262+ [ "E" ] => dl. endian = Endian :: Big ,
263+ [ p] if p. starts_with ( 'P' ) => {
264+ dl. instruction_address_space = parse_address_space ( & p[ 1 ..] , "P" ) ?
265+ }
266+ [ "a" , ref a @ ..] => dl. aggregate_align = align ( a, "a" ) ?,
267+ [ "f32" , ref a @ ..] => dl. f32_align = align ( a, "f32" ) ?,
268+ [ "f64" , ref a @ ..] => dl. f64_align = align ( a, "f64" ) ?,
269+ [ p @ "p" , s, ref a @ ..] | [ p @ "p0" , s, ref a @ ..] => {
270+ dl. pointer_size = size ( s, p) ?;
271+ dl. pointer_align = align ( a, p) ?;
272+ }
273+ [ s, ref a @ ..] if s. starts_with ( 'i' ) => {
274+ let Ok ( bits) = s[ 1 ..] . parse :: < u64 > ( ) else {
275+ size ( & s[ 1 ..] , "i" ) ?; // For the user error.
276+ continue ;
277+ } ;
278+ let a = align ( a, s) ?;
279+ match bits {
280+ 1 => dl. i1_align = a,
281+ 8 => dl. i8_align = a,
282+ 16 => dl. i16_align = a,
283+ 32 => dl. i32_align = a,
284+ 64 => dl. i64_align = a,
285+ _ => { }
286+ }
287+ if bits >= i128_align_src && bits <= 128 {
288+ // Default alignment for i128 is decided by taking the alignment of
289+ // largest-sized i{64..=128}.
290+ i128_align_src = bits;
291+ dl. i128_align = a;
292+ }
293+ }
294+ [ s, ref a @ ..] if s. starts_with ( 'v' ) => {
295+ let v_size = size ( & s[ 1 ..] , "v" ) ?;
296+ let a = align ( a, s) ?;
297+ if let Some ( v) = dl. vector_align . iter_mut ( ) . find ( |v| v. 0 == v_size) {
298+ v. 1 = a;
299+ continue ;
300+ }
301+ // No existing entry, add a new one.
302+ dl. vector_align . push ( ( v_size, a) ) ;
303+ }
304+ _ => { } // Ignore everything else.
305+ }
306+ }
307+ Ok ( dl)
308+ }
309+
214310 /// Returns exclusive upper bound on object size.
215311 ///
216312 /// The theoretical maximum object size is defined as the maximum positive `isize` value.
0 commit comments