@@ -130,8 +130,7 @@ impl<'tcx> GotocCtx<'tcx> {
130130 }
131131 ConstValue :: ByRef { alloc, offset } => {
132132 debug ! ( "ConstValue by ref {:?} {:?}" , alloc, offset) ;
133- let mem_var = self
134- . codegen_allocation_auto_imm_name ( alloc. inner ( ) , |tcx| tcx. next_global_name ( ) ) ;
133+ let mem_var = self . codegen_const_allocation ( alloc. inner ( ) , None ) ;
135134 mem_var
136135 . cast_to ( Type :: unsigned_int ( 8 ) . to_pointer ( ) )
137136 . plus ( Expr :: int_constant ( offset. bytes ( ) , Type :: unsigned_int ( 64 ) ) )
@@ -165,8 +164,7 @@ impl<'tcx> GotocCtx<'tcx> {
165164 // These seem to always start at 0
166165 assert_eq ! ( start, 0 ) ;
167166 // Create a static variable that holds its value
168- let mem_var =
169- self . codegen_allocation_auto_imm_name ( data, |tcx| tcx. next_global_name ( ) ) ;
167+ let mem_var = self . codegen_const_allocation ( data, None ) ;
170168
171169 // Extract identifier for static variable.
172170 // codegen_allocation_auto_imm_name returns the *address* of
@@ -464,15 +462,15 @@ impl<'tcx> GotocCtx<'tcx> {
464462 // crates do not conflict. The name alone is insufficient because Rust
465463 // allows different versions of the same crate to be used.
466464 let name = format ! ( "{}::{alloc_id:?}" , self . full_crate_name( ) ) ;
467- self . codegen_allocation ( alloc. inner ( ) , |_| name . clone ( ) , Some ( name. clone ( ) ) )
465+ self . codegen_const_allocation ( alloc. inner ( ) , Some ( name) )
468466 }
469467 GlobalAlloc :: VTable ( ty, trait_ref) => {
470468 // This is similar to GlobalAlloc::Memory but the type is opaque to rust and it
471469 // requires a bit more logic to get information about the allocation.
472470 let alloc_id = self . tcx . vtable_allocation ( ( ty, trait_ref) ) ;
473471 let alloc = self . tcx . global_alloc ( alloc_id) . unwrap_memory ( ) ;
474472 let name = format ! ( "{}::{alloc_id:?}" , self . full_crate_name( ) ) ;
475- self . codegen_allocation ( alloc. inner ( ) , |_| name . clone ( ) , Some ( name. clone ( ) ) )
473+ self . codegen_const_allocation ( alloc. inner ( ) , Some ( name) )
476474 }
477475 } ;
478476 assert ! ( res_t. is_pointer( ) || res_t. is_transparent_type( & self . symbol_table) ) ;
@@ -530,77 +528,36 @@ impl<'tcx> GotocCtx<'tcx> {
530528 sym. clone ( ) . to_expr ( ) . address_of ( )
531529 }
532530
533- /// `codegen_allocation` but without an `imm_name`
531+ /// Generate an expression that represents the address for a constant allocation.
534532 ///
535- /// TODO: This could use some refactoring. This function is only ever invoked as:
536- /// `self.codegen_allocation_auto_imm_name(alloc, |tcx| tcx.next_global_name())`
537- fn codegen_allocation_auto_imm_name < F : FnOnce ( & mut GotocCtx < ' tcx > ) -> String > (
538- & mut self ,
539- alloc : & ' tcx Allocation ,
540- mut_name : F ,
541- ) -> Expr {
542- self . codegen_allocation ( alloc, mut_name, None )
543- }
544-
545- /// Add a new static allocation to the symbol table (if not already present) and
546- /// generate a goto expression that points to it.
547- ///
548- /// This is *the* mechanism for generating (and ensuring the intialization of) a global
549- /// (often but not necessarily immutable) variable in the symbol table.
550- ///
551- /// We need to codegen allocations from two sources:
552- /// 1. `codegen_static` which supplies the initialization code for top-level statics.
553- /// 2. Constants, scattered throughout the source, which need to be initialized statically,
554- /// so those functions can reference them. (These should always be immutable.)
555- /// (These also require de-duplication.)
556- ///
557- /// TODO: This function could use some refactoring. Outside of `codegen_allocation_auto_imm_name`
558- /// above, this function is only ever invoked as:
559- /// `self.codegen_allocation(alloc, |_| name.clone(), Some(name.clone()))`
560- pub fn codegen_allocation < F : FnOnce ( & mut GotocCtx < ' tcx > ) -> String > (
561- & mut self ,
562- alloc : & ' tcx Allocation ,
563- mut_name : F ,
564- imm_name : Option < String > ,
565- ) -> Expr {
566- debug ! ( "codegen_allocation imm_name {:?}" , imm_name) ;
567- let mem_var = match alloc. mutability {
568- Mutability :: Mut => {
569- let name = mut_name ( self ) ;
570- self . codegen_alloc_in_memory ( alloc, name. clone ( ) ) ;
571- // here we know name must be in the symbol table
572- self . symbol_table . lookup ( & name) . unwrap ( ) . clone ( ) . to_expr ( )
573- }
574- Mutability :: Not => self . codegen_immutable_allocation ( alloc, imm_name) ,
575- } ;
576- mem_var. address_of ( )
577- }
578-
579- /// Generate a goto expression for an immutable (constant) allocation.
533+ /// This function will only allocate a new memory location if necessary. The standard does
534+ /// not offer any guarantees over the location of a constant.
580535 ///
581- /// This function's primary purpose is to de-duplicate immutable global constants.
582- /// If it already has been codegen'd, use that.
583- /// If not, we otherwise proceed identically to the mutable case and call `codegen_alloc_in_memory`
584- fn codegen_immutable_allocation (
585- & mut self ,
586- alloc : & ' tcx Allocation ,
587- name : Option < String > ,
588- ) -> Expr {
536+ /// These constants can be named constants which are declared by the user, or constant values
537+ /// used scattered throughout the source
538+ fn codegen_const_allocation ( & mut self , alloc : & ' tcx Allocation , name : Option < String > ) -> Expr {
539+ debug ! ( ?name, "codegen_const_allocation" ) ;
540+ assert_eq ! (
541+ alloc. mutability,
542+ Mutability :: Not ,
543+ "Expected constant allocation for `{name:?}`, but got a mutable instead"
544+ ) ;
589545 if !self . alloc_map . contains_key ( & alloc) {
590546 let name = if let Some ( name) = name { name } else { self . next_global_name ( ) } ;
591547 self . codegen_alloc_in_memory ( alloc, name) ;
592548 }
593549
594- self . symbol_table . lookup ( & self . alloc_map . get ( & alloc) . unwrap ( ) ) . unwrap ( ) . to_expr ( )
550+ let mem_place =
551+ self . symbol_table . lookup ( & self . alloc_map . get ( & alloc) . unwrap ( ) ) . unwrap ( ) . to_expr ( ) ;
552+ mem_place. address_of ( )
595553 }
596554
597555 /// Insert an allocation into the goto symbol table, and generate a goto function that will
598556 /// initialize it.
599557 ///
600558 /// This function is ultimately responsible for creating new statically initialized global variables
601- /// in our goto binaries. These may be actual (potentially mutable) globals or (more often) constants
602- /// that were encountered during code generation (that are of course immutable).
603- fn codegen_alloc_in_memory ( & mut self , alloc : & ' tcx Allocation , name : String ) {
559+ /// in our goto binaries.
560+ pub fn codegen_alloc_in_memory ( & mut self , alloc : & ' tcx Allocation , name : String ) {
604561 debug ! ( "codegen_alloc_in_memory name: {}" , name) ;
605562 let struct_name = & format ! ( "{name}::struct" ) ;
606563
0 commit comments