@@ -27,6 +27,8 @@ use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo};
27
27
use self :: operand:: { OperandRef , OperandValue } ;
28
28
use self :: place:: PlaceRef ;
29
29
30
+ const MIN_DANGEROUS_SIZE : u64 = 1024 * 1024 * 1024 * 1 ; // 1 GB
31
+
30
32
// Used for tracking the state of generated basic blocks.
31
33
enum CachedLlbb < T > {
32
34
/// Nothing created yet.
@@ -227,6 +229,16 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
227
229
let layout = start_bx. layout_of ( fx. monomorphize ( decl. ty ) ) ;
228
230
assert ! ( !layout. ty. has_erasable_regions( ) ) ;
229
231
232
+ if layout. size . bytes ( ) >= MIN_DANGEROUS_SIZE {
233
+ let size_str = || {
234
+ let ( size_quantity, size_unit) = human_readable_bytes ( layout. size . bytes ( ) ) ;
235
+ format ! ( "{:.2} {}" , size_quantity, size_unit)
236
+ } ;
237
+ span_bug ! ( decl. source_info. span, "Dangerous stack allocation, size: {:?} of local: {:?} exceeds typical limits on most architectures" ,
238
+ size_str( ) , local) ;
239
+
240
+ }
241
+
230
242
if local == mir:: RETURN_PLACE && fx. fn_abi . ret . is_indirect ( ) {
231
243
debug ! ( "alloc: {:?} (return place) -> place" , local) ;
232
244
let llretptr = start_bx. get_param ( 0 ) ;
@@ -276,6 +288,18 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
276
288
}
277
289
}
278
290
291
+ /// Formats a number of bytes into a human readable SI-prefixed size.
292
+ /// Returns a tuple of `(quantity, units)`.
293
+ //
294
+ // Taken from Cargo:
295
+ // https://github.com/rust-lang/cargo/blob/2ce45605d9db521b5fd6c1211ce8de6055fdb24e/src/cargo/util/mod.rs#L88-L95
296
+ pub fn human_readable_bytes ( bytes : u64 ) -> ( f32 , & ' static str ) {
297
+ static UNITS : [ & str ; 7 ] = [ "B" , "KiB" , "MiB" , "GiB" , "TiB" , "PiB" , "EiB" ] ;
298
+ let bytes = bytes as f32 ;
299
+ let i = ( ( bytes. log2 ( ) / 10.0 ) as usize ) . min ( UNITS . len ( ) - 1 ) ;
300
+ ( bytes / 1024_f32 . powi ( i as i32 ) , UNITS [ i] )
301
+ }
302
+
279
303
/// Produces, for each argument, a `Value` pointing at the
280
304
/// argument's value. As arguments are places, these are always
281
305
/// indirect.
0 commit comments