cfg.rs 73 KB

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