소스 검색

Polkadot: Do not emit the storage initializer twice (#1500)

Cyrill Leutwiler 2 년 전
부모
커밋
f70e1595ca
3개의 변경된 파일19개의 추가작업 그리고 30개의 파일을 삭제
  1. 4 4
      src/codegen/mod.rs
  2. 1 23
      src/emit/functions.rs
  3. 14 3
      src/emit/polkadot/mod.rs

+ 4 - 4
src/codegen/mod.rs

@@ -53,6 +53,9 @@ use solang_parser::{pt, pt::CodeLocation};
 // The sizeof(struct account_data_header)
 pub const SOLANA_FIRST_OFFSET: u64 = 16;
 
+/// Name of the storage initializer function
+pub const STORAGE_INITIALIZER: &str = "storage_initializer";
+
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 pub enum OptimizationLevel {
     None = 0,
@@ -253,10 +256,7 @@ fn contract(contract_no: usize, ns: &mut Namespace, opt: &Options) {
 /// This function will set all contract storage initializers and should be called from the constructor
 fn storage_initializer(contract_no: usize, ns: &mut Namespace, opt: &Options) -> ControlFlowGraph {
     // note the single `:` to prevent a name clash with user-declared functions
-    let mut cfg = ControlFlowGraph::new(
-        format!("{}:storage_initializer", ns.contracts[contract_no].name),
-        ASTFunction::None,
-    );
+    let mut cfg = ControlFlowGraph::new(STORAGE_INITIALIZER.to_string(), ASTFunction::None);
     let mut vartab = Vartable::new(ns.next_id);
 
     for layout in &ns.contracts[contract_no].layout {

+ 1 - 23
src/emit/functions.rs

@@ -4,7 +4,7 @@ use crate::{
     emit::{binary::Binary, cfg::emit_cfg, TargetRuntime},
     sema::ast::{Contract, Namespace, Type},
 };
-use inkwell::{module::Linkage, values::FunctionValue};
+use inkwell::module::Linkage;
 
 /// Emit all functions, constructors, fallback and receiver
 pub(super) fn emit_functions<'a, T: TargetRuntime<'a>>(
@@ -49,25 +49,3 @@ pub(super) fn emit_functions<'a, T: TargetRuntime<'a>>(
         emit_cfg(target, bin, contract, cfg, func_decl, ns);
     }
 }
-
-/// Emit the storage initializers
-pub(super) fn emit_initializer<'a, T: TargetRuntime<'a>>(
-    target: &mut T,
-    bin: &mut Binary<'a>,
-    contract: &Contract,
-    ns: &Namespace,
-) -> FunctionValue<'a> {
-    let function_ty = bin.function_type(&[], &[], ns);
-
-    let function = bin.module.add_function(
-        &format!("sol::{}::storage_initializers", contract.name),
-        function_ty,
-        Some(Linkage::Internal),
-    );
-
-    let cfg = &contract.cfg[contract.initializer.unwrap()];
-
-    emit_cfg(target, bin, contract, cfg, function, ns);
-
-    function
-}

+ 14 - 3
src/emit/polkadot/mod.rs

@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: Apache-2.0
 
-use crate::codegen::Options;
+use std::ffi::CString;
+
+use crate::codegen::{Options, STORAGE_INITIALIZER};
 use crate::sema::ast::{Contract, Namespace};
 use inkwell::context::Context;
 use inkwell::module::{Linkage, Module};
@@ -8,7 +10,7 @@ use inkwell::values::{BasicMetadataValueEnum, FunctionValue, IntValue, PointerVa
 use inkwell::AddressSpace;
 
 use crate::codegen::dispatch::polkadot::DispatchType;
-use crate::emit::functions::{emit_functions, emit_initializer};
+use crate::emit::functions::emit_functions;
 use crate::emit::{Binary, TargetRuntime};
 
 mod storage;
@@ -144,7 +146,16 @@ impl PolkadotTarget {
 
         emit_functions(&mut target, &mut binary, contract, ns);
 
-        let storage_initializer = emit_initializer(&mut target, &mut binary, contract, ns);
+        let function_name = CString::new(STORAGE_INITIALIZER).unwrap();
+        let mut storage_initializers = binary
+            .functions
+            .values()
+            .filter(|f| f.get_name() == function_name.as_c_str());
+        let storage_initializer = *storage_initializers
+            .next()
+            .expect("storage initializer is always present");
+        assert!(storage_initializers.next().is_none());
+
         target.emit_dispatch(Some(storage_initializer), &mut binary, ns);
         target.emit_dispatch(None, &mut binary, ns);