cfg.rs 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185
  1. // SPDX-License-Identifier: Apache-2.0
  2. use super::statements::{statement, LoopScopes};
  3. use super::{
  4. constant_folding, dead_storage,
  5. expression::expression,
  6. reaching_definitions, strength_reduce,
  7. vartable::{Vars, Vartable},
  8. vector_to_slice, Options,
  9. };
  10. use crate::codegen::subexpression_elimination::common_sub_expression_elimination;
  11. use crate::codegen::{undefined_variable, Expression, LLVMName};
  12. use crate::sema::ast::{
  13. CallTy, Contract, FunctionAttributes, Namespace, Parameter, RetrieveType, Statement,
  14. StringLocation, StructType, Type,
  15. };
  16. use crate::sema::{contracts::collect_base_args, diagnostics::Diagnostics, Recurse};
  17. use crate::{sema::ast, Target};
  18. use indexmap::IndexMap;
  19. use num_bigint::BigInt;
  20. use num_traits::One;
  21. use parse_display::Display;
  22. use solang_parser::pt::CodeLocation;
  23. use solang_parser::pt::Loc;
  24. use solang_parser::pt::{self, FunctionTy};
  25. use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
  26. use std::ops::AddAssign;
  27. use std::str;
  28. use std::sync::Arc;
  29. use std::{fmt, fmt::Write};
  30. // IndexMap <ArrayVariable res , res of temp variable>
  31. pub type ArrayLengthVars = IndexMap<usize, usize>;
  32. #[derive(Debug, Clone)]
  33. #[allow(clippy::large_enum_variant)]
  34. pub enum Instr {
  35. /// Set variable
  36. Set {
  37. loc: pt::Loc,
  38. res: usize,
  39. expr: Expression,
  40. },
  41. /// Call internal function, either static dispatch or dynamic dispatch
  42. Call {
  43. res: Vec<usize>,
  44. return_tys: Vec<Type>,
  45. call: InternalCallTy,
  46. args: Vec<Expression>,
  47. },
  48. /// Return
  49. Return { value: Vec<Expression> },
  50. /// Jump unconditionally
  51. Branch { block: usize },
  52. /// Jump conditionally
  53. BranchCond {
  54. cond: Expression,
  55. true_block: usize,
  56. false_block: usize,
  57. },
  58. /// Set array element in memory
  59. Store { dest: Expression, data: Expression },
  60. /// Abort execution
  61. AssertFailure { encoded_args: Option<Expression> },
  62. /// Print to log message
  63. Print { expr: Expression },
  64. /// Load storage (this is an instruction rather than an expression
  65. /// so that it can be moved around by the dead storage pass
  66. LoadStorage {
  67. res: usize,
  68. ty: Type,
  69. storage: Expression,
  70. },
  71. /// Clear storage at slot for ty (might span multiple slots)
  72. ClearStorage { ty: Type, storage: Expression },
  73. /// Set storage value at slot
  74. SetStorage {
  75. ty: Type,
  76. value: Expression,
  77. storage: Expression,
  78. },
  79. /// In storage slot, set the value at the offset
  80. SetStorageBytes {
  81. value: Expression,
  82. storage: Expression,
  83. offset: Expression,
  84. },
  85. /// Push an element onto an array in storage
  86. PushStorage {
  87. res: usize,
  88. ty: Type,
  89. value: Option<Expression>,
  90. storage: Expression,
  91. },
  92. /// Pop an element from an array in storage
  93. PopStorage {
  94. res: Option<usize>,
  95. ty: Type,
  96. storage: Expression,
  97. },
  98. /// Push element on memory array
  99. PushMemory {
  100. res: usize,
  101. ty: Type,
  102. array: usize,
  103. value: Box<Expression>,
  104. },
  105. /// Pop element from memory array. The push builtin returns a reference
  106. /// to the new element which is stored in res.
  107. PopMemory {
  108. res: usize,
  109. ty: Type,
  110. array: usize,
  111. loc: Loc,
  112. },
  113. /// Create contract and call constructor. If creating the contract fails,
  114. /// either store the result in success or abort success.
  115. Constructor {
  116. success: Option<usize>,
  117. res: usize,
  118. contract_no: usize,
  119. constructor_no: Option<usize>,
  120. encoded_args: Expression,
  121. value: Option<Expression>,
  122. gas: Expression,
  123. salt: Option<Expression>,
  124. address: Option<Expression>,
  125. seeds: Option<Expression>,
  126. accounts: Option<Expression>,
  127. loc: Loc,
  128. },
  129. /// Call external functions. If the call fails, set the success failure
  130. /// or abort if this is None
  131. ExternalCall {
  132. loc: Loc,
  133. success: Option<usize>,
  134. address: Option<Expression>,
  135. accounts: Option<Expression>,
  136. seeds: Option<Expression>,
  137. payload: Expression,
  138. value: Expression,
  139. gas: Expression,
  140. callty: CallTy,
  141. contract_function_no: Option<(usize, usize)>,
  142. flags: Option<Expression>,
  143. },
  144. /// Value transfer; either address.send() or address.transfer()
  145. ValueTransfer {
  146. success: Option<usize>,
  147. address: Expression,
  148. value: Expression,
  149. },
  150. /// Self destruct
  151. SelfDestruct { recipient: Expression },
  152. /// Emit event
  153. EmitEvent {
  154. event_no: usize,
  155. data: Expression,
  156. topics: Vec<Expression>,
  157. },
  158. /// Write Buffer
  159. WriteBuffer {
  160. buf: Expression,
  161. offset: Expression,
  162. value: Expression,
  163. },
  164. /// Copy bytes from source address to destination address
  165. MemCopy {
  166. source: Expression,
  167. destination: Expression,
  168. bytes: Expression,
  169. },
  170. Switch {
  171. cond: Expression,
  172. cases: Vec<(Expression, usize)>,
  173. default: usize,
  174. },
  175. /// Do nothing
  176. Nop,
  177. /// Return AbiEncoded data via an environment system call
  178. ReturnData {
  179. data: Expression,
  180. data_len: Expression,
  181. },
  182. /// Return a code at the end of a function
  183. ReturnCode { code: ReturnCode },
  184. /// For unimplemented code, e.g. unsupported yul builtins. This instruction should
  185. /// only occur for the evm target, for which no emit is implemented yet. Once evm emit
  186. /// is implemented and all yul builtins are supported, this instruction should
  187. /// be removed. We only have this so we can pass evm code through sema/codegen, which is used
  188. /// by the language server and the ethereum solidity tests.
  189. Unimplemented { reachable: bool },
  190. /// This instruction serves to track account accesses through 'tx.accounts.my_account'
  191. /// on Solana, and has no emit implementation. It is exchanged by the proper
  192. /// Expression::Subscript at solana_accounts/account_management.rs
  193. AccountAccess {
  194. loc: pt::Loc,
  195. var_no: usize,
  196. name: String,
  197. },
  198. }
  199. /// This struct defined the return codes that we send to the execution environment when we return
  200. /// from a function.
  201. #[derive(PartialEq, Eq, Hash, Clone, Debug, Display)]
  202. #[display(style = "title case")]
  203. pub enum ReturnCode {
  204. Success,
  205. FunctionSelectorInvalid,
  206. AbiEncodingInvalid,
  207. InvalidDataError,
  208. AccountDataTooSmall,
  209. InvalidProgramId,
  210. }
  211. impl Instr {
  212. pub fn recurse_expressions<T>(
  213. &self,
  214. cx: &mut T,
  215. f: fn(expr: &Expression, ctx: &mut T) -> bool,
  216. ) {
  217. match self {
  218. Instr::BranchCond { cond: expr, .. }
  219. | Instr::LoadStorage { storage: expr, .. }
  220. | Instr::ClearStorage { storage: expr, .. }
  221. | Instr::Print { expr }
  222. | Instr::AssertFailure {
  223. encoded_args: Some(expr),
  224. }
  225. | Instr::PopStorage { storage: expr, .. }
  226. | Instr::SelfDestruct { recipient: expr }
  227. | Instr::Set { expr, .. } => {
  228. expr.recurse(cx, f);
  229. }
  230. Instr::PushMemory { value: expr, .. } => {
  231. expr.recurse(cx, f);
  232. }
  233. Instr::SetStorage {
  234. value: item_1,
  235. storage: item_2,
  236. ..
  237. }
  238. | Instr::Store {
  239. dest: item_1,
  240. data: item_2,
  241. }
  242. | Instr::ReturnData {
  243. data: item_1,
  244. data_len: item_2,
  245. } => {
  246. item_1.recurse(cx, f);
  247. item_2.recurse(cx, f);
  248. }
  249. Instr::PushStorage { value, storage, .. } => {
  250. if let Some(value) = value {
  251. value.recurse(cx, f);
  252. }
  253. storage.recurse(cx, f);
  254. }
  255. Instr::SetStorageBytes {
  256. value,
  257. storage,
  258. offset,
  259. } => {
  260. value.recurse(cx, f);
  261. storage.recurse(cx, f);
  262. offset.recurse(cx, f);
  263. }
  264. Instr::Return { value: exprs } | Instr::Call { args: exprs, .. } => {
  265. for expr in exprs {
  266. expr.recurse(cx, f);
  267. }
  268. }
  269. Instr::Constructor {
  270. encoded_args,
  271. value,
  272. gas,
  273. salt,
  274. address,
  275. accounts,
  276. ..
  277. } => {
  278. encoded_args.recurse(cx, f);
  279. if let Some(expr) = value {
  280. expr.recurse(cx, f);
  281. }
  282. gas.recurse(cx, f);
  283. if let Some(expr) = salt {
  284. expr.recurse(cx, f);
  285. }
  286. if let Some(expr) = address {
  287. expr.recurse(cx, f);
  288. }
  289. if let Some(expr) = accounts {
  290. expr.recurse(cx, f);
  291. }
  292. }
  293. Instr::ExternalCall {
  294. address,
  295. payload,
  296. value,
  297. gas,
  298. ..
  299. } => {
  300. if let Some(expr) = address {
  301. expr.recurse(cx, f);
  302. }
  303. payload.recurse(cx, f);
  304. value.recurse(cx, f);
  305. gas.recurse(cx, f);
  306. }
  307. Instr::ValueTransfer { address, value, .. } => {
  308. address.recurse(cx, f);
  309. value.recurse(cx, f);
  310. }
  311. Instr::EmitEvent { data, topics, .. } => {
  312. data.recurse(cx, f);
  313. for expr in topics {
  314. expr.recurse(cx, f);
  315. }
  316. }
  317. Instr::WriteBuffer { offset, value, .. } => {
  318. value.recurse(cx, f);
  319. offset.recurse(cx, f);
  320. }
  321. Instr::MemCopy {
  322. source: from,
  323. destination: to,
  324. bytes,
  325. } => {
  326. from.recurse(cx, f);
  327. to.recurse(cx, f);
  328. bytes.recurse(cx, f);
  329. }
  330. Instr::Switch { cond, cases, .. } => {
  331. cond.recurse(cx, f);
  332. for (case, _) in cases {
  333. case.recurse(cx, f);
  334. }
  335. }
  336. Instr::AssertFailure { encoded_args: None }
  337. | Instr::Nop
  338. | Instr::ReturnCode { .. }
  339. | Instr::Branch { .. }
  340. | Instr::AccountAccess { .. }
  341. | Instr::PopMemory { .. }
  342. | Instr::Unimplemented { .. } => {}
  343. }
  344. }
  345. }
  346. #[derive(Clone, Debug)]
  347. #[allow(clippy::large_enum_variant)]
  348. pub enum InternalCallTy {
  349. Static { cfg_no: usize },
  350. Dynamic(Expression),
  351. Builtin { ast_func_no: usize },
  352. }
  353. #[derive(Clone, PartialEq, Eq)]
  354. pub enum HashTy {
  355. Keccak256,
  356. Ripemd160,
  357. Sha256,
  358. Blake2_256,
  359. Blake2_128,
  360. }
  361. impl fmt::Display for HashTy {
  362. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  363. match self {
  364. HashTy::Keccak256 => write!(f, "keccak256"),
  365. HashTy::Ripemd160 => write!(f, "ripemd160"),
  366. HashTy::Sha256 => write!(f, "sha256"),
  367. HashTy::Blake2_128 => write!(f, "blake2_128"),
  368. HashTy::Blake2_256 => write!(f, "blake2_256"),
  369. }
  370. }
  371. }
  372. #[derive(Debug, Clone, Default)]
  373. pub struct BasicBlock {
  374. pub phis: Option<BTreeSet<usize>>,
  375. pub name: String,
  376. pub instr: Vec<Instr>,
  377. pub defs: reaching_definitions::VarDefs,
  378. pub loop_reaching_variables: HashSet<usize>,
  379. pub transfers: Vec<Vec<reaching_definitions::Transfer>>,
  380. }
  381. #[derive(Debug, Clone)]
  382. pub struct ControlFlowGraph {
  383. pub name: String,
  384. pub function_no: ASTFunction,
  385. pub params: Arc<Vec<Parameter>>,
  386. pub returns: Arc<Vec<Parameter>>,
  387. pub vars: Vars,
  388. pub blocks: Vec<BasicBlock>,
  389. pub nonpayable: bool,
  390. pub public: bool,
  391. pub ty: pt::FunctionTy,
  392. pub selector: Vec<u8>,
  393. current: usize,
  394. // A mapping between the res of an array and the res of the temp var holding its length.
  395. pub array_lengths_temps: ArrayLengthVars,
  396. /// Is this a modifier dispatch for which function number?
  397. pub modifier: Option<usize>,
  398. }
  399. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  400. pub enum ASTFunction {
  401. SolidityFunction(usize),
  402. YulFunction(usize),
  403. None,
  404. }
  405. impl BasicBlock {
  406. /// Fetch the blocks that can be executed after the block passed as argument
  407. pub fn successors(&self) -> Vec<usize> {
  408. let mut out = Vec::new();
  409. // out cfg has edge as the last instruction in a block
  410. for (i, instr) in self.instr.iter().rev().enumerate() {
  411. match instr {
  412. Instr::Branch { block } => {
  413. assert_eq!(i, 0, "Branch is not last instruction in block");
  414. out.push(*block);
  415. }
  416. Instr::BranchCond {
  417. true_block,
  418. false_block,
  419. ..
  420. } => {
  421. assert_eq!(i, 0, "BranchCond is not last instruction in block");
  422. out.push(*true_block);
  423. out.push(*false_block);
  424. }
  425. Instr::Switch { default, cases, .. } => {
  426. assert_eq!(i, 0, "Switch is not last instruction in block");
  427. out.push(*default);
  428. for (_, goto) in cases {
  429. out.push(*goto);
  430. }
  431. }
  432. Instr::AssertFailure { .. }
  433. | Instr::SelfDestruct { .. }
  434. | Instr::ReturnCode { .. }
  435. | Instr::ReturnData { .. }
  436. | Instr::Return { .. }
  437. | Instr::Unimplemented { reachable: false } => {
  438. assert_eq!(i, 0, "instruction should be last in block");
  439. }
  440. _ => {
  441. assert_ne!(i, 0, "instruction should not be last in block");
  442. }
  443. }
  444. }
  445. out
  446. }
  447. }
  448. impl ControlFlowGraph {
  449. pub fn new(name: String, function_no: ASTFunction) -> Self {
  450. let mut cfg = ControlFlowGraph {
  451. name,
  452. function_no,
  453. params: Arc::new(Vec::new()),
  454. returns: Arc::new(Vec::new()),
  455. vars: IndexMap::new(),
  456. blocks: Vec::new(),
  457. nonpayable: false,
  458. public: false,
  459. ty: pt::FunctionTy::Function,
  460. selector: Vec::new(),
  461. current: 0,
  462. array_lengths_temps: IndexMap::new(),
  463. modifier: None,
  464. };
  465. cfg.new_basic_block("entry".to_string());
  466. cfg
  467. }
  468. /// Create an empty CFG which will be replaced later
  469. pub fn placeholder() -> Self {
  470. ControlFlowGraph {
  471. name: String::new(),
  472. function_no: ASTFunction::None,
  473. params: Arc::new(Vec::new()),
  474. returns: Arc::new(Vec::new()),
  475. vars: IndexMap::new(),
  476. blocks: Vec::new(),
  477. nonpayable: false,
  478. public: false,
  479. ty: pt::FunctionTy::Function,
  480. selector: Vec::new(),
  481. current: 0,
  482. array_lengths_temps: IndexMap::new(),
  483. modifier: None,
  484. }
  485. }
  486. /// Is this a placeholder
  487. pub fn is_placeholder(&self) -> bool {
  488. self.blocks.is_empty()
  489. }
  490. pub fn new_basic_block(&mut self, name: String) -> usize {
  491. let pos = self.blocks.len();
  492. self.blocks.push(BasicBlock {
  493. name,
  494. instr: Vec::new(),
  495. phis: None,
  496. transfers: Vec::new(),
  497. defs: IndexMap::new(),
  498. loop_reaching_variables: HashSet::new(),
  499. });
  500. pos
  501. }
  502. pub fn set_phis(&mut self, block: usize, phis: BTreeSet<usize>) {
  503. if !phis.is_empty() {
  504. self.blocks[block].phis = Some(phis);
  505. }
  506. }
  507. pub fn set_basic_block(&mut self, pos: usize) {
  508. self.current = pos;
  509. }
  510. /// Add an instruction to the CFG
  511. pub fn add(&mut self, vartab: &mut Vartable, ins: Instr) {
  512. if let Instr::Set { res, .. } = ins {
  513. vartab.set_dirty(res);
  514. }
  515. self.blocks[self.current].instr.push(ins);
  516. }
  517. /// Retrieve the basic block being processed
  518. pub fn current_block(&self) -> usize {
  519. self.current
  520. }
  521. /// Function to modify array length temp by inserting an add/sub instruction in the cfg right after a push/pop instruction.
  522. /// The operands of the add/sub instruction are the temp variable, and +/- 1.
  523. pub fn modify_temp_array_length(
  524. &mut self,
  525. loc: pt::Loc,
  526. minus: bool, // If the function is called from pushMemory or popMemory
  527. array_pos: usize, // The res of array that push/pop is performed on
  528. vartab: &mut Vartable,
  529. ) {
  530. // If not empty
  531. if self.array_lengths_temps.contains_key(&array_pos) {
  532. let to_add = self.array_lengths_temps[&array_pos];
  533. let add_expr = if minus {
  534. Expression::Subtract {
  535. loc,
  536. ty: Type::Uint(32),
  537. overflowing: true,
  538. left: Box::new(Expression::Variable {
  539. loc,
  540. ty: Type::Uint(32),
  541. var_no: to_add,
  542. }),
  543. right: Box::new(Expression::NumberLiteral {
  544. loc,
  545. ty: Type::Uint(32),
  546. value: BigInt::one(),
  547. }),
  548. }
  549. } else {
  550. Expression::Add {
  551. loc,
  552. ty: Type::Uint(32),
  553. overflowing: true,
  554. left: Box::new(Expression::Variable {
  555. loc,
  556. ty: Type::Uint(32),
  557. var_no: to_add,
  558. }),
  559. right: Box::new(Expression::NumberLiteral {
  560. loc,
  561. ty: Type::Uint(32),
  562. value: BigInt::one(),
  563. }),
  564. }
  565. };
  566. // Add instruction to the cfg
  567. self.add(
  568. vartab,
  569. Instr::Set {
  570. loc,
  571. res: to_add,
  572. expr: add_expr,
  573. },
  574. );
  575. }
  576. }
  577. pub fn expr_to_string(&self, contract: &Contract, ns: &Namespace, expr: &Expression) -> String {
  578. match expr {
  579. Expression::FunctionArg { arg_no, .. } => format!("(arg #{arg_no})"),
  580. Expression::BoolLiteral { value: false, .. } => "false".to_string(),
  581. Expression::BoolLiteral { value: true, .. } => "true".to_string(),
  582. Expression::BytesLiteral {
  583. ty: Type::String,
  584. value,
  585. ..
  586. } => {
  587. format!("{}", String::from_utf8_lossy(value))
  588. }
  589. Expression::BytesLiteral { value, .. } => format!("hex\"{}\"", hex::encode(value)),
  590. Expression::NumberLiteral {
  591. ty: ty @ Type::Address(_),
  592. value,
  593. ..
  594. } => {
  595. format!("{} {:#x}", ty.to_string(ns), value)
  596. }
  597. Expression::NumberLiteral { ty, value, .. } => {
  598. format!("{} {}", ty.to_string(ns), value)
  599. }
  600. Expression::RationalNumberLiteral { ty, rational, .. } => {
  601. format!("{} {}", ty.to_string(ns), rational)
  602. }
  603. Expression::StructLiteral { values, .. } => format!(
  604. "struct {{ {} }}",
  605. values
  606. .iter()
  607. .map(|e| self.expr_to_string(contract, ns, e))
  608. .collect::<Vec<String>>()
  609. .join(", ")
  610. ),
  611. Expression::ConstArrayLiteral {
  612. dimensions, values, ..
  613. } => format!(
  614. "constant {} [ {} ]",
  615. dimensions
  616. .iter()
  617. .map(|d| format!("[{d}]"))
  618. .collect::<String>(),
  619. values
  620. .iter()
  621. .map(|e| self.expr_to_string(contract, ns, e))
  622. .collect::<Vec<String>>()
  623. .join(", ")
  624. ),
  625. Expression::ArrayLiteral {
  626. dimensions, values, ..
  627. } => format!(
  628. "{} [ {} ]",
  629. dimensions
  630. .iter()
  631. .map(|d| format!("[{d}]"))
  632. .collect::<String>(),
  633. values
  634. .iter()
  635. .map(|e| self.expr_to_string(contract, ns, e))
  636. .collect::<Vec<String>>()
  637. .join(", ")
  638. ),
  639. Expression::Add {
  640. overflowing,
  641. left,
  642. right,
  643. ..
  644. } => format!(
  645. "({}{} + {})",
  646. if *overflowing { "overflowing " } else { "" },
  647. self.expr_to_string(contract, ns, left),
  648. self.expr_to_string(contract, ns, right)
  649. ),
  650. Expression::Subtract {
  651. overflowing,
  652. left,
  653. right,
  654. ..
  655. } => format!(
  656. "({}{} - {})",
  657. if *overflowing { "overflowing " } else { "" },
  658. self.expr_to_string(contract, ns, left),
  659. self.expr_to_string(contract, ns, right)
  660. ),
  661. Expression::BitwiseOr { left, right, .. } => format!(
  662. "({} | {})",
  663. self.expr_to_string(contract, ns, left),
  664. self.expr_to_string(contract, ns, right)
  665. ),
  666. Expression::BitwiseAnd { left, right, .. } => format!(
  667. "({} & {})",
  668. self.expr_to_string(contract, ns, left),
  669. self.expr_to_string(contract, ns, right)
  670. ),
  671. Expression::BitwiseXor { left, right, .. } => format!(
  672. "({} ^ {})",
  673. self.expr_to_string(contract, ns, left),
  674. self.expr_to_string(contract, ns, right)
  675. ),
  676. Expression::ShiftLeft { left, right, .. } => format!(
  677. "({} << {})",
  678. self.expr_to_string(contract, ns, left),
  679. self.expr_to_string(contract, ns, right)
  680. ),
  681. Expression::ShiftRight { left, right, .. } => format!(
  682. "({} >> {})",
  683. self.expr_to_string(contract, ns, left),
  684. self.expr_to_string(contract, ns, right)
  685. ),
  686. Expression::Multiply {
  687. overflowing,
  688. left,
  689. right,
  690. ..
  691. } => format!(
  692. "({}{} * {})",
  693. if *overflowing { "overflowing " } else { "" },
  694. self.expr_to_string(contract, ns, left),
  695. self.expr_to_string(contract, ns, right)
  696. ),
  697. Expression::SignedDivide { left, right, .. } => format!(
  698. "(signed divide {} / {})",
  699. self.expr_to_string(contract, ns, left),
  700. self.expr_to_string(contract, ns, right),
  701. ),
  702. Expression::UnsignedDivide { left, right, .. } => format!(
  703. "(unsigned divide {} / {})",
  704. self.expr_to_string(contract, ns, left),
  705. self.expr_to_string(contract, ns, right),
  706. ),
  707. Expression::SignedModulo { left, right, .. } => format!(
  708. "(signed modulo {} % {})",
  709. self.expr_to_string(contract, ns, left),
  710. self.expr_to_string(contract, ns, right)
  711. ),
  712. Expression::UnsignedModulo { left, right, .. } => format!(
  713. "(unsigned modulo {} % {})",
  714. self.expr_to_string(contract, ns, left),
  715. self.expr_to_string(contract, ns, right)
  716. ),
  717. Expression::Power {
  718. overflowing,
  719. base,
  720. exp,
  721. ..
  722. } => format!(
  723. "({}{} ** {})",
  724. if *overflowing { "overflowing " } else { "" },
  725. self.expr_to_string(contract, ns, base),
  726. self.expr_to_string(contract, ns, exp)
  727. ),
  728. Expression::Variable { var_no, .. } => {
  729. if let Some(var) = self.vars.get(var_no) {
  730. format!("%{}", var.id.name)
  731. } else {
  732. panic!("error: non-existing variable {var_no} in CFG");
  733. }
  734. }
  735. Expression::Load { expr, .. } => {
  736. format!("(load {})", self.expr_to_string(contract, ns, expr))
  737. }
  738. Expression::ZeroExt { ty, expr, .. } => format!(
  739. "(zext {} {})",
  740. ty.to_string(ns),
  741. self.expr_to_string(contract, ns, expr)
  742. ),
  743. Expression::SignExt { ty, expr, .. } => format!(
  744. "(sext {} {})",
  745. ty.to_string(ns),
  746. self.expr_to_string(contract, ns, expr)
  747. ),
  748. Expression::Trunc { ty, expr, .. } => format!(
  749. "(trunc {} {})",
  750. ty.to_string(ns),
  751. self.expr_to_string(contract, ns, expr)
  752. ),
  753. Expression::More {
  754. signed,
  755. left,
  756. right,
  757. ..
  758. } => format!(
  759. "({} more {} > {})",
  760. if *signed { "signed" } else { "unsigned" },
  761. self.expr_to_string(contract, ns, left),
  762. self.expr_to_string(contract, ns, right)
  763. ),
  764. Expression::Less {
  765. signed,
  766. left,
  767. right,
  768. ..
  769. } => format!(
  770. "({} less {} < {})",
  771. if *signed { "signed" } else { "unsigned" },
  772. self.expr_to_string(contract, ns, left),
  773. self.expr_to_string(contract, ns, right)
  774. ),
  775. Expression::MoreEqual {
  776. signed,
  777. left,
  778. right,
  779. ..
  780. } => format!(
  781. "({} {} >= {})",
  782. if *signed { "signed" } else { "unsigned" },
  783. self.expr_to_string(contract, ns, left),
  784. self.expr_to_string(contract, ns, right)
  785. ),
  786. Expression::LessEqual {
  787. signed,
  788. left,
  789. right,
  790. ..
  791. } => format!(
  792. "({} {} <= {})",
  793. if *signed { "signed" } else { "unsigned" },
  794. self.expr_to_string(contract, ns, left),
  795. self.expr_to_string(contract, ns, right)
  796. ),
  797. Expression::Equal { left, right, .. } => format!(
  798. "({} == {})",
  799. self.expr_to_string(contract, ns, left),
  800. self.expr_to_string(contract, ns, right)
  801. ),
  802. Expression::NotEqual { left, right, .. } => format!(
  803. "({} != {})",
  804. self.expr_to_string(contract, ns, left),
  805. self.expr_to_string(contract, ns, right)
  806. ),
  807. Expression::Subscript {
  808. array_ty: ty,
  809. expr,
  810. index,
  811. ..
  812. } => format!(
  813. "(subscript {} {}[{}])",
  814. ty.to_string(ns),
  815. self.expr_to_string(contract, ns, expr),
  816. self.expr_to_string(contract, ns, index)
  817. ),
  818. Expression::StorageArrayLength { array, elem_ty, .. } => format!(
  819. "(storage array length {}[{}])",
  820. self.expr_to_string(contract, ns, array),
  821. elem_ty.to_string(ns),
  822. ),
  823. Expression::StructMember { expr, member, .. } => format!(
  824. "(struct {} field {})",
  825. self.expr_to_string(contract, ns, expr),
  826. member
  827. ),
  828. Expression::Not { expr, .. } => {
  829. format!("!{}", self.expr_to_string(contract, ns, expr))
  830. }
  831. Expression::BitwiseNot { expr, .. } => {
  832. format!("~{}", self.expr_to_string(contract, ns, expr))
  833. }
  834. Expression::Negate { expr, .. } => {
  835. format!("-{}", self.expr_to_string(contract, ns, expr))
  836. }
  837. Expression::Poison => "☠".to_string(),
  838. Expression::AllocDynamicBytes {
  839. ty,
  840. size,
  841. initializer: None,
  842. ..
  843. } => {
  844. let ty = if let Type::Slice(ty) = ty {
  845. format!("slice {}", ty.to_string(ns))
  846. } else {
  847. ty.to_string(ns)
  848. };
  849. format!(
  850. "(alloc {} len {})",
  851. ty,
  852. self.expr_to_string(contract, ns, size)
  853. )
  854. }
  855. Expression::AllocDynamicBytes {
  856. ty,
  857. size,
  858. initializer: Some(init),
  859. ..
  860. } => {
  861. let ty = if let Type::Slice(ty) = ty {
  862. format!("slice {}", ty.to_string(ns))
  863. } else {
  864. ty.to_string(ns)
  865. };
  866. format!(
  867. "(alloc {} {} {})",
  868. ty,
  869. self.expr_to_string(contract, ns, size),
  870. match str::from_utf8(init) {
  871. Ok(s) => format!("\"{}\"", s.escape_debug()),
  872. Err(_) => format!("hex\"{}\"", hex::encode(init)),
  873. }
  874. )
  875. }
  876. Expression::StringCompare { left, right, .. } => format!(
  877. "(strcmp ({}) ({}))",
  878. self.location_to_string(contract, ns, left),
  879. self.location_to_string(contract, ns, right)
  880. ),
  881. Expression::StringConcat { left, right, .. } => format!(
  882. "(concat ({}) ({}))",
  883. self.location_to_string(contract, ns, left),
  884. self.location_to_string(contract, ns, right)
  885. ),
  886. Expression::Keccak256 { exprs, .. } => format!(
  887. "(keccak256 {})",
  888. exprs
  889. .iter()
  890. .map(|e| self.expr_to_string(contract, ns, e))
  891. .collect::<Vec<String>>()
  892. .join(", ")
  893. ),
  894. Expression::InternalFunctionCfg { cfg_no, .. } => {
  895. format!("function {}", contract.cfg[*cfg_no].name)
  896. }
  897. Expression::ReturnData { .. } => "(external call return data)".to_string(),
  898. Expression::Cast { ty, expr, .. } => format!(
  899. "{}({})",
  900. ty.to_string(ns),
  901. self.expr_to_string(contract, ns, expr)
  902. ),
  903. Expression::BytesCast { ty, from, expr, .. } => format!(
  904. "{} from:{} ({})",
  905. ty.to_string(ns),
  906. from.to_string(ns),
  907. self.expr_to_string(contract, ns, expr)
  908. ),
  909. Expression::Builtin {
  910. kind: builtin,
  911. args,
  912. ..
  913. } => format!(
  914. "(builtin {:?} ({}))",
  915. builtin,
  916. args.iter()
  917. .map(|a| self.expr_to_string(contract, ns, a))
  918. .collect::<Vec<String>>()
  919. .join(", ")
  920. ),
  921. Expression::FormatString { args: fields, .. } => format!(
  922. "(format string {})",
  923. fields
  924. .iter()
  925. .map(|(spec, a)| format!("({} {})", spec, self.expr_to_string(contract, ns, a)))
  926. .collect::<Vec<String>>()
  927. .join(", ")
  928. ),
  929. Expression::Undefined { .. } => "undef".to_string(),
  930. Expression::AdvancePointer {
  931. pointer,
  932. bytes_offset,
  933. } => {
  934. format!(
  935. "(advance ptr: {}, by: {})",
  936. self.expr_to_string(contract, ns, pointer),
  937. self.expr_to_string(contract, ns, bytes_offset)
  938. )
  939. }
  940. Expression::GetRef { expr, .. } => {
  941. format!("(deref {}", self.expr_to_string(contract, ns, expr))
  942. }
  943. _ => panic!("{expr:?}"),
  944. }
  945. }
  946. fn location_to_string(
  947. &self,
  948. contract: &Contract,
  949. ns: &Namespace,
  950. l: &StringLocation<Expression>,
  951. ) -> String {
  952. match l {
  953. StringLocation::RunTime(e) => self.expr_to_string(contract, ns, e),
  954. StringLocation::CompileTime(literal) => match str::from_utf8(literal) {
  955. Ok(s) => format!("\"{}\"", s.to_owned()),
  956. Err(_) => format!("hex\"{}\"", hex::encode(literal)),
  957. },
  958. }
  959. }
  960. pub fn instr_to_string(&self, contract: &Contract, ns: &Namespace, instr: &Instr) -> String {
  961. match instr {
  962. Instr::Return { value } => format!(
  963. "return {}",
  964. value
  965. .iter()
  966. .map(|expr| self.expr_to_string(contract, ns, expr))
  967. .collect::<Vec<String>>()
  968. .join(", ")
  969. ),
  970. Instr::Set { res, expr, .. } => format!(
  971. "ty:{} %{} = {}",
  972. self.vars[res].ty.to_string(ns),
  973. self.vars[res].id.name,
  974. self.expr_to_string(contract, ns, expr)
  975. ),
  976. Instr::Branch { block } => format!("branch block{block}"),
  977. Instr::BranchCond {
  978. cond,
  979. true_block,
  980. false_block,
  981. } => format!(
  982. "branchcond {}, block{}, block{}",
  983. self.expr_to_string(contract, ns, cond),
  984. true_block,
  985. false_block,
  986. ),
  987. Instr::LoadStorage { ty, res, storage } => format!(
  988. "%{} = load storage slot({}) ty:{}",
  989. self.vars[res].id.name,
  990. self.expr_to_string(contract, ns, storage),
  991. ty.to_string(ns),
  992. ),
  993. Instr::ClearStorage { ty, storage } => format!(
  994. "clear storage slot({}) ty:{}",
  995. self.expr_to_string(contract, ns, storage),
  996. ty.to_string(ns),
  997. ),
  998. Instr::SetStorage { ty, value, storage } => format!(
  999. "store storage slot({}) ty:{} = {}",
  1000. self.expr_to_string(contract, ns, storage),
  1001. ty.to_string(ns),
  1002. self.expr_to_string(contract, ns, value),
  1003. ),
  1004. Instr::SetStorageBytes {
  1005. value,
  1006. storage,
  1007. offset,
  1008. } => format!(
  1009. "set storage slot({}) offset:{} = {}",
  1010. self.expr_to_string(contract, ns, storage),
  1011. self.expr_to_string(contract, ns, offset),
  1012. self.expr_to_string(contract, ns, value),
  1013. ),
  1014. Instr::PushStorage {
  1015. res,
  1016. ty,
  1017. storage,
  1018. value,
  1019. } => {
  1020. format!(
  1021. "%{} = push storage ty:{} slot:{} = {}",
  1022. self.vars[res].id.name,
  1023. ty.to_string(ns),
  1024. self.expr_to_string(contract, ns, storage),
  1025. if let Some(value) = value {
  1026. self.expr_to_string(contract, ns, value)
  1027. } else {
  1028. String::from("empty")
  1029. }
  1030. )
  1031. }
  1032. Instr::PopStorage {
  1033. res: Some(res),
  1034. ty,
  1035. storage,
  1036. } => {
  1037. format!(
  1038. "%{} = pop storage ty:{} slot({})",
  1039. self.vars[res].id.name,
  1040. ty.to_string(ns),
  1041. self.expr_to_string(contract, ns, storage),
  1042. )
  1043. }
  1044. Instr::PopStorage {
  1045. res: None,
  1046. ty,
  1047. storage,
  1048. } => {
  1049. format!(
  1050. "pop storage ty:{} slot({})",
  1051. ty.to_string(ns),
  1052. self.expr_to_string(contract, ns, storage),
  1053. )
  1054. }
  1055. Instr::PushMemory {
  1056. res,
  1057. ty,
  1058. array,
  1059. value,
  1060. } => format!(
  1061. "%{}, %{} = push array ty:{} value:{}",
  1062. self.vars[res].id.name,
  1063. self.vars[array].id.name,
  1064. ty.to_string(ns),
  1065. self.expr_to_string(contract, ns, value),
  1066. ),
  1067. Instr::PopMemory { res, ty, array, loc:_ } => format!(
  1068. "%{}, %{} = pop array ty:{}",
  1069. self.vars[res].id.name,
  1070. self.vars[array].id.name,
  1071. ty.to_string(ns),
  1072. ),
  1073. Instr::AssertFailure { encoded_args: None } => "assert-failure".to_string(),
  1074. Instr::AssertFailure { encoded_args: Some(expr) } => {
  1075. format!("assert-failure: buffer: {}",
  1076. self.expr_to_string(contract, ns, expr),
  1077. )
  1078. }
  1079. Instr::Call {
  1080. res,
  1081. call: InternalCallTy::Builtin { ast_func_no },
  1082. args,
  1083. ..
  1084. } => format!(
  1085. "{} = call builtin {} {}",
  1086. res.iter()
  1087. .map(|local| format!("%{}", self.vars[local].id.name))
  1088. .collect::<Vec<String>>()
  1089. .join(", "),
  1090. ns.functions[*ast_func_no].name,
  1091. args.iter()
  1092. .map(|expr| self.expr_to_string(contract, ns, expr))
  1093. .collect::<Vec<String>>()
  1094. .join(", ")
  1095. ),
  1096. Instr::Call {
  1097. res,
  1098. call: InternalCallTy::Static { cfg_no },
  1099. args,
  1100. ..
  1101. } => format!(
  1102. "{} = call {} {}",
  1103. res.iter()
  1104. .map(|local| format!("%{}", self.vars[local].id.name))
  1105. .collect::<Vec<String>>()
  1106. .join(", "),
  1107. contract.cfg[*cfg_no].name,
  1108. args.iter()
  1109. .map(|expr| self.expr_to_string(contract, ns, expr))
  1110. .collect::<Vec<String>>()
  1111. .join(", ")
  1112. ),
  1113. Instr::Call {
  1114. res,
  1115. call: InternalCallTy::Dynamic(cfg),
  1116. args,
  1117. ..
  1118. } => format!(
  1119. "{} = call {} {}",
  1120. res.iter()
  1121. .map(|local| format!("%{}", self.vars[local].id.name))
  1122. .collect::<Vec<String>>()
  1123. .join(", "),
  1124. self.expr_to_string(contract, ns, cfg),
  1125. args.iter()
  1126. .map(|expr| self.expr_to_string(contract, ns, expr))
  1127. .collect::<Vec<String>>()
  1128. .join(", ")
  1129. ),
  1130. Instr::ExternalCall {
  1131. success,
  1132. address,
  1133. payload,
  1134. value,
  1135. accounts,
  1136. seeds,
  1137. gas,
  1138. callty,
  1139. contract_function_no,
  1140. flags, ..
  1141. } => {
  1142. format!(
  1143. "{} = external call::{} address:{} payload:{} value:{} gas:{} accounts:{} seeds:{} contract|function:{} flags:{}",
  1144. match success {
  1145. Some(i) => format!("%{}", self.vars[i].id.name),
  1146. None => "_".to_string(),
  1147. },
  1148. callty,
  1149. if let Some(address) = address {
  1150. self.expr_to_string(contract, ns, address)
  1151. } else {
  1152. String::new()
  1153. },
  1154. self.expr_to_string(contract, ns, payload),
  1155. self.expr_to_string(contract, ns, value),
  1156. self.expr_to_string(contract, ns, gas),
  1157. if let Some(accounts) = accounts {
  1158. self.expr_to_string(contract, ns, accounts)
  1159. } else {
  1160. String::new()
  1161. },
  1162. if let Some(seeds) = seeds {
  1163. self.expr_to_string(contract, ns, seeds)
  1164. } else {
  1165. String::new()
  1166. },
  1167. if let Some((contract_no, function_no)) = contract_function_no {
  1168. format!("({contract_no}, {function_no})")
  1169. } else {
  1170. "_".to_string()
  1171. },
  1172. flags.as_ref().map(|e| self.expr_to_string(contract, ns, e)).unwrap_or_default()
  1173. )
  1174. }
  1175. Instr::ValueTransfer {
  1176. success,
  1177. address,
  1178. value,
  1179. } => {
  1180. format!(
  1181. "{} = value transfer address:{} value:{}",
  1182. match success {
  1183. Some(i) => format!("%{}", self.vars[i].id.name),
  1184. None => "_".to_string(),
  1185. },
  1186. self.expr_to_string(contract, ns, address),
  1187. self.expr_to_string(contract, ns, value),
  1188. )
  1189. }
  1190. Instr::Store { dest, data } => format!(
  1191. "store {}, {}",
  1192. self.expr_to_string(contract, ns, dest),
  1193. self.expr_to_string(contract, ns, data),
  1194. ),
  1195. Instr::Print { expr } => format!("print {}", self.expr_to_string(contract, ns, expr)),
  1196. Instr::Constructor {
  1197. success,
  1198. res,
  1199. contract_no,
  1200. encoded_args,
  1201. gas,
  1202. salt,
  1203. value,
  1204. address,seeds,
  1205. accounts,
  1206. constructor_no,
  1207. loc:_
  1208. } => format!(
  1209. "%{}, {} = constructor(no: {}) salt:{} value:{} gas:{} address:{} seeds:{} {} encoded buffer: {} accounts: {}",
  1210. self.vars[res].id.name,
  1211. match success {
  1212. Some(i) => format!("%{}", self.vars[i].id.name),
  1213. None => "_".to_string(),
  1214. },
  1215. if let Some(no) = constructor_no {
  1216. format!("{}", no)
  1217. } else {
  1218. String::new()
  1219. },
  1220. match salt {
  1221. Some(salt) => self.expr_to_string(contract, ns, salt),
  1222. None => "".to_string(),
  1223. },
  1224. match value {
  1225. Some(value) => self.expr_to_string(contract, ns, value),
  1226. None => "".to_string(),
  1227. },
  1228. self.expr_to_string(contract, ns, gas),
  1229. match address {
  1230. Some(address) => self.expr_to_string(contract, ns, address),
  1231. None => "".to_string(),
  1232. },
  1233. if let Some(seeds) = seeds {
  1234. self.expr_to_string(contract, ns, seeds)
  1235. } else {
  1236. String::new()
  1237. },
  1238. ns.contracts[*contract_no].name,
  1239. self.expr_to_string(contract, ns, encoded_args),
  1240. if let Some(accounts) = accounts {
  1241. self.expr_to_string(contract, ns, accounts)
  1242. } else {
  1243. String::new()
  1244. }
  1245. ),
  1246. Instr::SelfDestruct { recipient } => format!(
  1247. "selfdestruct {}",
  1248. self.expr_to_string(contract, ns, recipient)
  1249. ),
  1250. Instr::WriteBuffer { buf, offset, value } => format!(
  1251. "writebuffer buffer:{} offset:{} value:{}",
  1252. self.expr_to_string(contract, ns, buf),
  1253. self.expr_to_string(contract, ns, offset),
  1254. self.expr_to_string(contract, ns, value)
  1255. ),
  1256. Instr::EmitEvent {
  1257. data,
  1258. topics,
  1259. event_no,
  1260. ..
  1261. } => format!(
  1262. "emit event {} topics {} data {} ",
  1263. ns.events[*event_no].symbol_name(ns),
  1264. topics
  1265. .iter()
  1266. .map(|expr| self.expr_to_string(contract, ns, expr))
  1267. .collect::<Vec<String>>()
  1268. .join(", "),
  1269. self.expr_to_string(contract, ns, data)
  1270. ),
  1271. Instr::Nop => String::from("nop"),
  1272. Instr::MemCopy {
  1273. source: from,
  1274. destination: to,
  1275. bytes,
  1276. } => {
  1277. format!(
  1278. "memcpy src: {}, dest: {}, bytes_len: {}",
  1279. self.expr_to_string(contract, ns, from),
  1280. self.expr_to_string(contract, ns, to),
  1281. self.expr_to_string(contract, ns, bytes)
  1282. )
  1283. }
  1284. Instr::Switch {
  1285. cond,
  1286. cases,
  1287. default,
  1288. } => {
  1289. let mut description =
  1290. format!("switch {}:", self.expr_to_string(contract, ns, cond),);
  1291. for item in cases {
  1292. description.push_str(
  1293. format!(
  1294. "\n\t\tcase {}: goto block #{}",
  1295. self.expr_to_string(contract, ns, &item.0),
  1296. item.1
  1297. )
  1298. .as_str(),
  1299. );
  1300. }
  1301. description.push_str(format!("\n\t\tdefault: goto block #{default}").as_str());
  1302. description
  1303. }
  1304. Instr::ReturnData { data, data_len } => {
  1305. format!(
  1306. "return data {}, data length: {}",
  1307. self.expr_to_string(contract, ns, data),
  1308. self.expr_to_string(contract, ns, data_len)
  1309. )
  1310. }
  1311. Instr::ReturnCode { code } => {
  1312. format!("return code: {code}")
  1313. }
  1314. Instr::Unimplemented { .. } => {
  1315. "unimplemented".into()
  1316. }
  1317. Instr::AccountAccess { .. } => {
  1318. unreachable!("Instr::AccountAccess shall never be in the final CFG")
  1319. }
  1320. }
  1321. }
  1322. pub fn basic_block_to_string(&self, contract: &Contract, ns: &Namespace, pos: usize) -> String {
  1323. let mut s = format!("block{}: # {}\n", pos, self.blocks[pos].name);
  1324. if let Some(ref phis) = self.blocks[pos].phis {
  1325. writeln!(
  1326. s,
  1327. "\t# phis: {}",
  1328. phis.iter()
  1329. .map(|p| -> &str { &self.vars[p].id.name })
  1330. .collect::<Vec<&str>>()
  1331. .join(",")
  1332. )
  1333. .unwrap();
  1334. }
  1335. let defs = &self.blocks[pos].defs;
  1336. if !defs.is_empty() {
  1337. writeln!(
  1338. s,
  1339. "\t# reaching:{}",
  1340. defs.iter()
  1341. .map(|(var_no, defs)| format!(
  1342. " {}:[{}]",
  1343. &self.vars[var_no].id.name,
  1344. defs.keys()
  1345. .map(|d| format!("{}:{}", d.block_no, d.instr_no))
  1346. .collect::<Vec<String>>()
  1347. .join(", ")
  1348. ))
  1349. .collect::<Vec<String>>()
  1350. .join(", ")
  1351. )
  1352. .unwrap();
  1353. }
  1354. for ins in &self.blocks[pos].instr {
  1355. writeln!(s, "\t{}", self.instr_to_string(contract, ns, ins)).unwrap();
  1356. }
  1357. s
  1358. }
  1359. pub fn to_string(&self, contract: &Contract, ns: &Namespace) -> String {
  1360. let mut s = String::from("");
  1361. for i in 0..self.blocks.len() {
  1362. s.push_str(&self.basic_block_to_string(contract, ns, i));
  1363. }
  1364. s
  1365. }
  1366. }
  1367. /// Checks whether there is a virtual fallback or receive function
  1368. fn is_there_virtual_function(
  1369. ns: &Namespace,
  1370. contract_no: usize,
  1371. function_no: Option<usize>,
  1372. ) -> bool {
  1373. let default_constructor = &ns.default_constructor(contract_no);
  1374. let func = match function_no {
  1375. Some(function_no) => &ns.functions[function_no],
  1376. None => default_constructor,
  1377. };
  1378. // if the function is a fallback or receive, then don't bother with the overriden functions; they cannot be used
  1379. if func.ty == pt::FunctionTy::Receive {
  1380. // if there is a virtual receive function, and it's not this one, ignore it
  1381. if let Some(receive) = ns.contracts[contract_no].virtual_functions.get("@receive") {
  1382. if Some(*receive) != function_no {
  1383. return true;
  1384. }
  1385. }
  1386. }
  1387. if func.ty == pt::FunctionTy::Fallback {
  1388. // if there is a virtual fallback function, and it's not this one, ignore it
  1389. if let Some(fallback) = ns.contracts[contract_no].virtual_functions.get("@fallback") {
  1390. if Some(*fallback) != function_no {
  1391. return true;
  1392. }
  1393. }
  1394. }
  1395. if func.ty == pt::FunctionTy::Modifier || !func.has_body {
  1396. return true;
  1397. }
  1398. false
  1399. }
  1400. /// Generate the CFG for a function. If function_no is None, generate the implicit default
  1401. /// constructor
  1402. pub fn generate_cfg(
  1403. contract_no: usize,
  1404. function_no: Option<usize>,
  1405. cfg_no: usize,
  1406. all_cfgs: &mut Vec<ControlFlowGraph>,
  1407. ns: &mut Namespace,
  1408. opt: &Options,
  1409. ) {
  1410. if is_there_virtual_function(ns, contract_no, function_no) {
  1411. return;
  1412. }
  1413. let mut cfg = function_cfg(contract_no, function_no, ns, opt);
  1414. let ast_fn = function_no
  1415. .map(ASTFunction::SolidityFunction)
  1416. .unwrap_or(ASTFunction::None);
  1417. optimize_and_check_cfg(&mut cfg, ns, ast_fn, opt);
  1418. if let Some(func_no) = function_no {
  1419. let func = &ns.functions[func_no];
  1420. // if the function has any modifiers, generate the modifier chain
  1421. if !func.modifiers.is_empty() {
  1422. // only function can have modifiers
  1423. assert_eq!(func.ty, pt::FunctionTy::Function);
  1424. let public = cfg.public;
  1425. let nonpayable = cfg.nonpayable;
  1426. cfg.public = false;
  1427. for chain_no in (0..func.modifiers.len()).rev() {
  1428. let modifier_cfg_no = all_cfgs.len();
  1429. all_cfgs.push(cfg);
  1430. cfg = generate_modifier_dispatch(
  1431. contract_no,
  1432. func_no,
  1433. modifier_cfg_no,
  1434. chain_no,
  1435. ns,
  1436. opt,
  1437. );
  1438. optimize_and_check_cfg(&mut cfg, ns, ast_fn, opt);
  1439. }
  1440. cfg.public = public;
  1441. cfg.nonpayable = nonpayable;
  1442. cfg.selector = ns.functions[func_no].selector(ns, &contract_no);
  1443. cfg.modifier = Some(func_no);
  1444. }
  1445. }
  1446. all_cfgs[cfg_no] = cfg;
  1447. }
  1448. /// resolve modifier call
  1449. fn resolve_modifier_call<'a>(
  1450. call: &'a ast::Expression,
  1451. contract: &Contract,
  1452. ) -> (usize, &'a Vec<ast::Expression>) {
  1453. if let ast::Expression::InternalFunctionCall { function, args, .. } = call {
  1454. if let ast::Expression::InternalFunction {
  1455. function_no,
  1456. signature,
  1457. ..
  1458. } = function.as_ref()
  1459. {
  1460. // is it a virtual function call
  1461. let function_no = if let Some(signature) = signature {
  1462. contract.virtual_functions[signature]
  1463. } else {
  1464. *function_no
  1465. };
  1466. return (function_no, args);
  1467. }
  1468. }
  1469. panic!("modifier should resolve to internal call");
  1470. }
  1471. /// Detect undefined variables and run codegen optimizer passess
  1472. pub fn optimize_and_check_cfg(
  1473. cfg: &mut ControlFlowGraph,
  1474. ns: &mut Namespace,
  1475. func_no: ASTFunction,
  1476. opt: &Options,
  1477. ) {
  1478. reaching_definitions::find(cfg);
  1479. if func_no != ASTFunction::None {
  1480. // If there are undefined variables, we raise an error and don't run optimizations
  1481. if undefined_variable::find_undefined_variables(cfg, ns, func_no) {
  1482. return;
  1483. }
  1484. }
  1485. // constant folding generates diagnostics, so always run it. This means that the diagnostics
  1486. // do not depend which passes are enabled. If the constant_folding is not enabled, run it
  1487. // dry mode.
  1488. constant_folding::constant_folding(cfg, !opt.constant_folding, ns);
  1489. if opt.vector_to_slice {
  1490. vector_to_slice::vector_to_slice(cfg, ns);
  1491. }
  1492. if opt.strength_reduce {
  1493. strength_reduce::strength_reduce(cfg, ns);
  1494. }
  1495. if opt.dead_storage {
  1496. dead_storage::dead_storage(cfg, ns);
  1497. }
  1498. // If the function is a default constructor, there is nothing to optimize.
  1499. if opt.common_subexpression_elimination && func_no != ASTFunction::None {
  1500. common_sub_expression_elimination(cfg, ns);
  1501. }
  1502. }
  1503. /// Generate the CFG for a function. If function_no is None, generate the implicit default
  1504. /// constructor
  1505. fn function_cfg(
  1506. contract_no: usize,
  1507. function_no: Option<usize>,
  1508. ns: &mut Namespace,
  1509. opt: &Options,
  1510. ) -> ControlFlowGraph {
  1511. let mut vartab = match function_no {
  1512. Some(function_no) => {
  1513. Vartable::from_symbol_table(&ns.functions[function_no].symtable, ns.next_id)
  1514. }
  1515. None => Vartable::new(ns.next_id),
  1516. };
  1517. let mut loops = LoopScopes::new();
  1518. let default_constructor = &ns.default_constructor(contract_no);
  1519. let func = match function_no {
  1520. Some(function_no) => &ns.functions[function_no],
  1521. None => default_constructor,
  1522. };
  1523. // symbol name
  1524. let contract_name = match func.contract_no {
  1525. Some(base_contract_no) => format!(
  1526. "{}::{}",
  1527. ns.contracts[contract_no].name, ns.contracts[base_contract_no].name
  1528. ),
  1529. None => ns.contracts[contract_no].name.to_string(),
  1530. };
  1531. let name = match func.ty {
  1532. pt::FunctionTy::Function => {
  1533. format!("{}::function::{}", contract_name, func.llvm_symbol(ns))
  1534. }
  1535. // There can be multiple constructors on Polkadot, give them an unique name
  1536. pt::FunctionTy::Constructor => {
  1537. format!(
  1538. "{}::constructor::{}",
  1539. contract_name,
  1540. hex::encode(func.selector(ns, &contract_no))
  1541. )
  1542. }
  1543. _ => format!("{}::{}", contract_name, func.ty),
  1544. };
  1545. let mut cfg = ControlFlowGraph::new(
  1546. name,
  1547. if let Some(num) = function_no {
  1548. ASTFunction::SolidityFunction(num)
  1549. } else {
  1550. ASTFunction::None
  1551. },
  1552. );
  1553. cfg.params = func.params.clone();
  1554. cfg.returns = func.returns.clone();
  1555. cfg.selector = func.selector(ns, &contract_no);
  1556. cfg.public = ns.function_externally_callable(contract_no, function_no);
  1557. cfg.ty = func.ty;
  1558. cfg.nonpayable = !func.is_payable();
  1559. // populate the argument variables
  1560. populate_arguments(func, &mut cfg, &mut vartab);
  1561. // Hold your breath, this is the trickest part of the codegen ahead.
  1562. // For each contract, the top-level constructor calls the base constructors. The base
  1563. // constructors do not call their base constructors; everything is called from the top
  1564. // level constructor. This is done because the arguments to base constructor are only
  1565. // known the top level constructor, since the arguments can be specified elsewhere
  1566. // on a constructor for a superior class
  1567. if func.ty == pt::FunctionTy::Constructor && func.contract_no == Some(contract_no) {
  1568. let mut all_base_args = BTreeMap::new();
  1569. let mut diagnostics = Diagnostics::default();
  1570. // Find all the resolved arguments for base contracts. These can be attached
  1571. // to the contract, or the constructor. Contracts can have multiple constructors
  1572. // so this needs to follow the correct constructors all the way
  1573. collect_base_args(
  1574. contract_no,
  1575. function_no,
  1576. &mut all_base_args,
  1577. &mut diagnostics,
  1578. ns,
  1579. );
  1580. // We shouldn't have problems. sema should have checked this
  1581. assert!(diagnostics.is_empty());
  1582. let order = ns.contract_bases(contract_no);
  1583. let mut gen_base_args: HashMap<usize, (usize, Vec<Expression>)> = HashMap::new();
  1584. for base_no in order.iter().rev() {
  1585. if *base_no == contract_no {
  1586. // we can't evaluate arguments to ourselves.
  1587. continue;
  1588. }
  1589. if let Some(base_args) = all_base_args.get(base_no) {
  1590. // There might be some temporary variables needed from the symbol table where
  1591. // the constructor arguments were defined
  1592. if let Some(defined_constructor_no) = base_args.defined_constructor_no {
  1593. let func = &ns.functions[defined_constructor_no];
  1594. vartab.add_symbol_table(&func.symtable);
  1595. }
  1596. // So we are evaluating the base arguments, from superior to inferior. The results
  1597. // must be stored somewhere, for two reasons:
  1598. // - The results must be stored by-value, so that variable value don't change
  1599. // by later base arguments (e.g. x++)
  1600. // - The results are also arguments to the next constructor arguments, so they
  1601. // might be used again. Therefore we store the result in the vartable entry
  1602. // for the argument; this means values are passed automatically to the next
  1603. // constructor. We do need the symbol table for the called constructor, therefore
  1604. // we have the following two lines which look a bit odd at first
  1605. let func = &ns.functions[base_args.calling_constructor_no];
  1606. vartab.add_symbol_table(&func.symtable);
  1607. let args: Vec<Expression> = base_args
  1608. .args
  1609. .iter()
  1610. .enumerate()
  1611. .map(|(i, a)| {
  1612. let expr =
  1613. expression(a, &mut cfg, contract_no, Some(func), ns, &mut vartab, opt);
  1614. if let Some(id) = &func.symtable.arguments[i] {
  1615. let ty = expr.ty();
  1616. let loc = expr.loc();
  1617. cfg.add(
  1618. &mut vartab,
  1619. Instr::Set {
  1620. loc: func.params[i].loc,
  1621. res: *id,
  1622. expr,
  1623. },
  1624. );
  1625. Expression::Variable {
  1626. loc,
  1627. ty,
  1628. var_no: *id,
  1629. }
  1630. } else {
  1631. Expression::Poison
  1632. }
  1633. })
  1634. .collect();
  1635. gen_base_args.insert(*base_no, (base_args.calling_constructor_no, args));
  1636. }
  1637. }
  1638. for base_no in order.iter() {
  1639. if *base_no == contract_no {
  1640. // we can't evaluate arguments to ourselves.
  1641. continue;
  1642. }
  1643. if let Some((constructor_no, args)) = gen_base_args.remove(base_no) {
  1644. let cfg_no = ns.contracts[contract_no].all_functions[&constructor_no];
  1645. cfg.add(
  1646. &mut vartab,
  1647. Instr::Call {
  1648. res: Vec::new(),
  1649. return_tys: Vec::new(),
  1650. call: InternalCallTy::Static { cfg_no },
  1651. args,
  1652. },
  1653. );
  1654. } else if let Some(constructor_no) = ns.contracts[*base_no].no_args_constructor(ns) {
  1655. let cfg_no = ns.contracts[contract_no].all_functions[&constructor_no];
  1656. cfg.add(
  1657. &mut vartab,
  1658. Instr::Call {
  1659. res: Vec::new(),
  1660. return_tys: Vec::new(),
  1661. call: InternalCallTy::Static { cfg_no },
  1662. args: Vec::new(),
  1663. },
  1664. );
  1665. }
  1666. }
  1667. }
  1668. // named returns should be populated
  1669. populate_named_returns(func, ns, &mut cfg, &mut vartab);
  1670. for stmt in &func.body {
  1671. statement(
  1672. stmt,
  1673. func,
  1674. &mut cfg,
  1675. contract_no,
  1676. ns,
  1677. &mut vartab,
  1678. &mut loops,
  1679. None,
  1680. None,
  1681. opt,
  1682. );
  1683. }
  1684. if func.body.last().map(Statement::reachable).unwrap_or(true) {
  1685. let loc = match func.body.last() {
  1686. Some(ins) => ins.loc(),
  1687. None => pt::Loc::Codegen,
  1688. };
  1689. // add implicit return
  1690. cfg.add(
  1691. &mut vartab,
  1692. Instr::Return {
  1693. value: func
  1694. .symtable
  1695. .returns
  1696. .iter()
  1697. .map(|pos| Expression::Variable {
  1698. loc,
  1699. ty: func.symtable.vars[pos].ty.clone(),
  1700. var_no: *pos,
  1701. })
  1702. .collect::<Vec<_>>(),
  1703. },
  1704. );
  1705. }
  1706. vartab.finalize(ns, &mut cfg);
  1707. // walk cfg to check for use for before initialize
  1708. cfg
  1709. }
  1710. /// Populate the arguments of a function
  1711. pub(crate) fn populate_arguments<T: FunctionAttributes>(
  1712. func: &T,
  1713. cfg: &mut ControlFlowGraph,
  1714. vartab: &mut Vartable,
  1715. ) {
  1716. for (i, arg) in func.get_symbol_table().arguments.iter().enumerate() {
  1717. if let Some(pos) = arg {
  1718. let var = &func.get_symbol_table().vars[pos];
  1719. cfg.add(
  1720. vartab,
  1721. Instr::Set {
  1722. loc: func.get_parameters()[i].loc,
  1723. res: *pos,
  1724. expr: Expression::FunctionArg {
  1725. loc: var.id.loc,
  1726. ty: var.ty.clone(),
  1727. arg_no: i,
  1728. },
  1729. },
  1730. );
  1731. }
  1732. }
  1733. }
  1734. /// Populate returns of functions that have named returns
  1735. pub(crate) fn populate_named_returns<T: FunctionAttributes>(
  1736. func: &T,
  1737. ns: &Namespace,
  1738. cfg: &mut ControlFlowGraph,
  1739. vartab: &mut Vartable,
  1740. ) {
  1741. for (i, pos) in func.get_symbol_table().returns.iter().enumerate() {
  1742. if let Some(name) = &func.get_returns()[i].id {
  1743. if let Some(expr) = func.get_returns()[i].ty.default(ns) {
  1744. cfg.add(
  1745. vartab,
  1746. Instr::Set {
  1747. loc: name.loc,
  1748. res: *pos,
  1749. expr,
  1750. },
  1751. );
  1752. }
  1753. }
  1754. }
  1755. }
  1756. /// Generate the CFG for a modifier on a function
  1757. fn generate_modifier_dispatch(
  1758. contract_no: usize,
  1759. func_no: usize,
  1760. cfg_no: usize,
  1761. chain_no: usize,
  1762. ns: &mut Namespace,
  1763. opt: &Options,
  1764. ) -> ControlFlowGraph {
  1765. let (modifier_no, args) = resolve_modifier_call(
  1766. &ns.functions[func_no].modifiers[chain_no],
  1767. &ns.contracts[contract_no],
  1768. );
  1769. let func = &ns.functions[func_no];
  1770. let modifier = &ns.functions[modifier_no];
  1771. let name = format!(
  1772. "{}::{}::{}::modifier{}::{}",
  1773. &ns.contracts[contract_no].name,
  1774. &ns.contracts[func.contract_no.unwrap()].name,
  1775. func.llvm_symbol(ns),
  1776. chain_no,
  1777. modifier.llvm_symbol(ns)
  1778. );
  1779. let mut cfg = ControlFlowGraph::new(name, ASTFunction::None);
  1780. cfg.params = func.params.clone();
  1781. cfg.returns = func.returns.clone();
  1782. let mut vartab = Vartable::from_symbol_table(&func.symtable, ns.next_id);
  1783. vartab.add_symbol_table(&modifier.symtable);
  1784. let mut loops = LoopScopes::new();
  1785. // a modifier takes the same arguments as the function it is applied to. This way we can pass
  1786. // the arguments to the function
  1787. for (i, arg) in func.symtable.arguments.iter().enumerate() {
  1788. if let Some(pos) = arg {
  1789. let var = &func.symtable.vars[pos];
  1790. cfg.add(
  1791. &mut vartab,
  1792. Instr::Set {
  1793. loc: var.id.loc,
  1794. res: *pos,
  1795. expr: Expression::FunctionArg {
  1796. loc: var.id.loc,
  1797. ty: var.ty.clone(),
  1798. arg_no: i,
  1799. },
  1800. },
  1801. );
  1802. }
  1803. }
  1804. // now set the modifier args
  1805. for (i, arg) in modifier.symtable.arguments.iter().enumerate() {
  1806. if let Some(pos) = arg {
  1807. let expr = expression(
  1808. &args[i],
  1809. &mut cfg,
  1810. contract_no,
  1811. Some(func),
  1812. ns,
  1813. &mut vartab,
  1814. opt,
  1815. );
  1816. cfg.add(
  1817. &mut vartab,
  1818. Instr::Set {
  1819. loc: expr.loc(),
  1820. res: *pos,
  1821. expr,
  1822. },
  1823. );
  1824. }
  1825. }
  1826. // modifiers do not have return values in their syntax, but the return values from the function
  1827. // need to be passed on. So, we need to create some var
  1828. let mut value = Vec::new();
  1829. let mut return_tys = Vec::new();
  1830. for (i, arg) in func.returns.iter().enumerate() {
  1831. value.push(Expression::Variable {
  1832. loc: arg.loc,
  1833. ty: arg.ty.clone(),
  1834. var_no: func.symtable.returns[i],
  1835. });
  1836. return_tys.push(arg.ty.clone());
  1837. }
  1838. let return_instr = Instr::Return { value };
  1839. // create the instruction for the place holder
  1840. let placeholder = Instr::Call {
  1841. res: func.symtable.returns.clone(),
  1842. call: InternalCallTy::Static { cfg_no },
  1843. return_tys,
  1844. args: func
  1845. .params
  1846. .iter()
  1847. .enumerate()
  1848. .map(|(i, p)| Expression::FunctionArg {
  1849. loc: p.loc,
  1850. ty: p.ty.clone(),
  1851. arg_no: i,
  1852. })
  1853. .collect(),
  1854. };
  1855. for stmt in &modifier.body {
  1856. statement(
  1857. stmt,
  1858. modifier,
  1859. &mut cfg,
  1860. contract_no,
  1861. ns,
  1862. &mut vartab,
  1863. &mut loops,
  1864. Some(&placeholder),
  1865. Some(&return_instr),
  1866. opt,
  1867. );
  1868. }
  1869. if modifier
  1870. .body
  1871. .last()
  1872. .map(Statement::reachable)
  1873. .unwrap_or(true)
  1874. {
  1875. let loc = match func.body.last() {
  1876. Some(ins) => ins.loc(),
  1877. None => pt::Loc::Codegen,
  1878. };
  1879. // add implicit return
  1880. cfg.add(
  1881. &mut vartab,
  1882. Instr::Return {
  1883. value: func
  1884. .symtable
  1885. .returns
  1886. .iter()
  1887. .map(|pos| Expression::Variable {
  1888. loc,
  1889. ty: func.symtable.vars[pos].ty.clone(),
  1890. var_no: *pos,
  1891. })
  1892. .collect::<Vec<_>>(),
  1893. },
  1894. );
  1895. }
  1896. vartab.finalize(ns, &mut cfg);
  1897. cfg
  1898. }
  1899. impl Contract {
  1900. /// Print the entire contract; storage initializers, constructors and functions and their CFGs
  1901. pub fn print_cfg(&self, ns: &Namespace) -> String {
  1902. let mut out = format!("#\n# Contract: {}\n#\n\n", self.name);
  1903. for cfg in &self.cfg {
  1904. if !cfg.is_placeholder() {
  1905. writeln!(
  1906. out,
  1907. "\n# {} {} public:{} selector:{} nonpayable:{}",
  1908. cfg.ty,
  1909. cfg.name,
  1910. cfg.public,
  1911. hex::encode(&cfg.selector),
  1912. cfg.nonpayable,
  1913. )
  1914. .unwrap();
  1915. writeln!(
  1916. out,
  1917. "# params: {}",
  1918. cfg.params
  1919. .iter()
  1920. .map(|p| {
  1921. if p.id.is_some() {
  1922. format!("{} {}", p.ty.to_string(ns), p.name_as_str())
  1923. } else {
  1924. p.ty.to_string(ns)
  1925. }
  1926. })
  1927. .collect::<Vec<String>>()
  1928. .join(",")
  1929. )
  1930. .unwrap();
  1931. writeln!(
  1932. out,
  1933. "# returns: {}",
  1934. cfg.returns
  1935. .iter()
  1936. .map(|p| {
  1937. if p.id.is_some() {
  1938. format!("{} {}", p.ty.to_string(ns), p.name_as_str())
  1939. } else {
  1940. p.ty.to_string(ns)
  1941. }
  1942. })
  1943. .collect::<Vec<String>>()
  1944. .join(",")
  1945. )
  1946. .unwrap();
  1947. out += &cfg.to_string(self, ns);
  1948. }
  1949. }
  1950. out
  1951. }
  1952. /// Get the storage slot for a variable, possibly from base contract
  1953. pub fn get_storage_slot(
  1954. &self,
  1955. loc: pt::Loc,
  1956. var_contract_no: usize,
  1957. var_no: usize,
  1958. ns: &Namespace,
  1959. ty: Option<Type>,
  1960. ) -> Expression {
  1961. if let Some(layout) = self
  1962. .layout
  1963. .iter()
  1964. .find(|l| l.contract_no == var_contract_no && l.var_no == var_no)
  1965. {
  1966. Expression::NumberLiteral {
  1967. loc,
  1968. ty: ty.unwrap_or_else(|| ns.storage_type()),
  1969. value: layout.slot.clone(),
  1970. }
  1971. } else {
  1972. panic!("get_storage_slot called on non-storage variable");
  1973. }
  1974. }
  1975. }
  1976. impl Namespace {
  1977. /// Determine whether a function should be included in the dispatcher and metadata,
  1978. /// taking inheritance into account.
  1979. ///
  1980. /// `function_no` is optional because default constructors require creating a CFG
  1981. /// without any corresponding function definition.
  1982. pub fn function_externally_callable(
  1983. &self,
  1984. contract_no: usize,
  1985. function_no: Option<usize>,
  1986. ) -> bool {
  1987. let default_constructor = &self.default_constructor(contract_no);
  1988. let func = function_no
  1989. .map(|n| &self.functions[n])
  1990. .unwrap_or(default_constructor);
  1991. // If a function is virtual, and it is overriden, do not make it public;
  1992. // Otherwise the runtime function dispatch will have two identical functions to dispatch to.
  1993. if func.is_virtual
  1994. && self.contracts[contract_no]
  1995. .virtual_functions
  1996. .get(&func.signature)
  1997. != function_no.as_ref()
  1998. {
  1999. return false;
  2000. }
  2001. if let Some(base_contract_no) = func.contract_no {
  2002. return !(self.contracts[base_contract_no].is_library()
  2003. || func.is_constructor() && contract_no != base_contract_no)
  2004. && func.is_public()
  2005. && func.ty != FunctionTy::Modifier;
  2006. }
  2007. false
  2008. }
  2009. /// Type storage
  2010. pub fn storage_type(&self) -> Type {
  2011. if self.target == Target::Solana {
  2012. Type::Uint(32)
  2013. } else {
  2014. Type::Uint(256)
  2015. }
  2016. }
  2017. /// Return the value type
  2018. pub fn value_type(&self) -> Type {
  2019. Type::Uint(8 * self.value_length as u16)
  2020. }
  2021. /// Checks if struct contains only primitive types and returns its memory non-padded size
  2022. pub fn calculate_struct_non_padded_size(&self, struct_type: &StructType) -> Option<BigInt> {
  2023. let mut size = BigInt::from(0u8);
  2024. for field in &struct_type.definition(self).fields {
  2025. let ty = field.ty.clone().unwrap_user_type(self);
  2026. if !ty.is_primitive() {
  2027. // If a struct contains a non-primitive type, we cannot calculate its
  2028. // size during compile time
  2029. if let Type::Struct(struct_ty) = &field.ty {
  2030. if let Some(struct_size) = self.calculate_struct_non_padded_size(struct_ty) {
  2031. size.add_assign(struct_size);
  2032. continue;
  2033. }
  2034. }
  2035. return None;
  2036. } else {
  2037. size.add_assign(ty.memory_size_of(self));
  2038. }
  2039. }
  2040. Some(size)
  2041. }
  2042. }