77///
88/// For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler,
99/// see design document in the tracking issue #89653.
10- use core:: fmt:: Display ;
1110use rustc_data_structures:: base_n;
1211use rustc_data_structures:: fx:: FxHashMap ;
1312use rustc_hir as hir;
13+ use rustc_middle:: ty:: layout:: IntegerExt ;
1414use rustc_middle:: ty:: {
1515 self , Const , ExistentialPredicate , FloatTy , FnSig , Instance , IntTy , List , Region , RegionKind ,
1616 TermKind , Ty , TyCtxt , UintTy ,
@@ -19,6 +19,7 @@ use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
1919use rustc_span:: def_id:: DefId ;
2020use rustc_span:: sym;
2121use rustc_target:: abi:: call:: { Conv , FnAbi } ;
22+ use rustc_target:: abi:: Integer ;
2223use rustc_target:: spec:: abi:: Abi ;
2324use std:: fmt:: Write as _;
2425
@@ -93,44 +94,54 @@ fn encode_const<'tcx>(
9394 dict : & mut FxHashMap < DictKey < ' tcx > , usize > ,
9495 options : EncodeTyOptions ,
9596) -> String {
96- // L<element-type>[n]<element-value>E as literal argument
97+ // L<element-type>[n][ <element-value>] E as literal argument
9798 let mut s = String :: from ( 'L' ) ;
9899
99- // Element type
100- s. push_str ( & encode_ty ( tcx, c. ty ( ) , dict, options) ) ;
100+ match c. kind ( ) {
101+ // Const parameters
102+ ty:: ConstKind :: Param ( ..) => {
103+ // L<element-type>E as literal argument
101104
102- // The only allowed types of const parameters are bool, u8, u16, u32, u64, u128, usize i8, i16,
103- // i32, i64, i128, isize, and char. The bool value false is encoded as 0 and true as 1.
104- fn push_signed_value < T : Display + PartialOrd > ( s : & mut String , value : T , zero : T ) {
105- if value < zero {
106- s. push ( 'n' )
107- } ;
108- let _ = write ! ( s, "{value}" ) ;
109- }
110-
111- fn push_unsigned_value < T : Display > ( s : & mut String , value : T ) {
112- let _ = write ! ( s, "{value}" ) ;
113- }
105+ // Element type
106+ s. push_str ( & encode_ty ( tcx, c. ty ( ) , dict, options) ) ;
107+ }
114108
115- if let Some ( scalar_int) = c. try_to_scalar_int ( ) {
116- let signed = c. ty ( ) . is_signed ( ) ;
117- match scalar_int. size ( ) . bits ( ) {
118- 8 if signed => push_signed_value ( & mut s, scalar_int. try_to_i8 ( ) . unwrap ( ) , 0 ) ,
119- 16 if signed => push_signed_value ( & mut s, scalar_int. try_to_i16 ( ) . unwrap ( ) , 0 ) ,
120- 32 if signed => push_signed_value ( & mut s, scalar_int. try_to_i32 ( ) . unwrap ( ) , 0 ) ,
121- 64 if signed => push_signed_value ( & mut s, scalar_int. try_to_i64 ( ) . unwrap ( ) , 0 ) ,
122- 128 if signed => push_signed_value ( & mut s, scalar_int. try_to_i128 ( ) . unwrap ( ) , 0 ) ,
123- 8 => push_unsigned_value ( & mut s, scalar_int. try_to_u8 ( ) . unwrap ( ) ) ,
124- 16 => push_unsigned_value ( & mut s, scalar_int. try_to_u16 ( ) . unwrap ( ) ) ,
125- 32 => push_unsigned_value ( & mut s, scalar_int. try_to_u32 ( ) . unwrap ( ) ) ,
126- 64 => push_unsigned_value ( & mut s, scalar_int. try_to_u64 ( ) . unwrap ( ) ) ,
127- 128 => push_unsigned_value ( & mut s, scalar_int. try_to_u128 ( ) . unwrap ( ) ) ,
128- _ => {
129- bug ! ( "encode_const: unexpected size `{:?}`" , scalar_int. size( ) . bits( ) ) ;
109+ // Literal arguments
110+ ty:: ConstKind :: Value ( ..) => {
111+ // L<element-type>[n]<element-value>E as literal argument
112+
113+ // Element type
114+ s. push_str ( & encode_ty ( tcx, c. ty ( ) , dict, options) ) ;
115+
116+ // The only allowed types of const values are bool, u8, u16, u32,
117+ // u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The
118+ // bool value false is encoded as 0 and true as 1.
119+ match c. ty ( ) . kind ( ) {
120+ ty:: Int ( ity) => {
121+ let bits = c. eval_bits ( tcx, ty:: ParamEnv :: reveal_all ( ) , c. ty ( ) ) ;
122+ let val = Integer :: from_int_ty ( & tcx, * ity) . size ( ) . sign_extend ( bits) as i128 ;
123+ if val < 0 {
124+ s. push ( 'n' ) ;
125+ }
126+ let _ = write ! ( s, "{val}" ) ;
127+ }
128+ ty:: Uint ( _) => {
129+ let val = c. eval_bits ( tcx, ty:: ParamEnv :: reveal_all ( ) , c. ty ( ) ) ;
130+ let _ = write ! ( s, "{val}" ) ;
131+ }
132+ ty:: Bool => {
133+ let val = c. try_eval_bool ( tcx, ty:: ParamEnv :: reveal_all ( ) ) . unwrap ( ) ;
134+ let _ = write ! ( s, "{val}" ) ;
135+ }
136+ _ => {
137+ bug ! ( "encode_const: unexpected type `{:?}`" , c. ty( ) ) ;
138+ }
130139 }
131- } ;
132- } else {
133- bug ! ( "encode_const: unexpected type `{:?}`" , c. ty( ) ) ;
140+ }
141+
142+ _ => {
143+ bug ! ( "encode_const: unexpected kind `{:?}`" , c. kind( ) ) ;
144+ }
134145 }
135146
136147 // Close the "L..E" pair
0 commit comments