mod.rs 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912
  1. // SPDX-License-Identifier: Apache-2.0
  2. mod array_boundary;
  3. pub mod cfg;
  4. mod constant_folding;
  5. mod constructor;
  6. mod dead_storage;
  7. pub(crate) mod dispatch;
  8. pub(crate) mod encoding;
  9. mod events;
  10. mod expression;
  11. pub(super) mod polkadot;
  12. mod reaching_definitions;
  13. pub mod revert;
  14. mod solana_accounts;
  15. mod solana_deploy;
  16. mod statements;
  17. mod storage;
  18. mod strength_reduce;
  19. pub(crate) mod subexpression_elimination;
  20. mod tests;
  21. mod undefined_variable;
  22. mod unused_variable;
  23. pub(crate) mod vartable;
  24. mod vector_to_slice;
  25. mod yul;
  26. use self::{
  27. cfg::{optimize_and_check_cfg, ControlFlowGraph, Instr},
  28. dispatch::function_dispatch,
  29. expression::expression,
  30. solana_accounts::account_collection::collect_accounts_from_contract,
  31. vartable::Vartable,
  32. };
  33. use crate::sema::ast::{
  34. FormatArg, Function, Layout, Namespace, RetrieveType, StringLocation, Type,
  35. };
  36. use crate::{sema::ast, Target};
  37. use std::cmp::Ordering;
  38. use crate::codegen::cfg::ASTFunction;
  39. use crate::codegen::solana_accounts::account_management::manage_contract_accounts;
  40. use crate::codegen::yul::generate_yul_function_cfg;
  41. use crate::sema::diagnostics::Diagnostics;
  42. use crate::sema::eval::eval_const_number;
  43. use crate::sema::Recurse;
  44. #[cfg(feature = "wasm_opt")]
  45. use contract_build::OptimizationPasses;
  46. use encoding::soroban_encoding::soroban_encode_arg;
  47. use num_bigint::{BigInt, Sign};
  48. use num_rational::BigRational;
  49. use num_traits::{FromPrimitive, Zero};
  50. use solang_parser::diagnostics::Diagnostic;
  51. use solang_parser::{pt, pt::CodeLocation};
  52. // The sizeof(struct account_data_header)
  53. pub const SOLANA_FIRST_OFFSET: u64 = 16;
  54. /// Name of the storage initializer function
  55. pub const STORAGE_INITIALIZER: &str = "storage_initializer";
  56. /// Maximum permitted size of account data (10 MiB).
  57. /// https://github.com/solana-labs/solana/blob/08aba38d3507c8cb66f85074d8f1249d43e64a75/sdk/program/src/system_instruction.rs#L85
  58. pub const MAXIMUM_ACCOUNT_SIZE: u64 = 10 * 1024 * 1024;
  59. #[derive(Debug, PartialEq, Eq, Copy, Clone)]
  60. pub enum OptimizationLevel {
  61. None = 0,
  62. Less = 1,
  63. Default = 2,
  64. Aggressive = 3,
  65. }
  66. #[cfg(feature = "llvm")]
  67. impl From<OptimizationLevel> for inkwell::OptimizationLevel {
  68. fn from(level: OptimizationLevel) -> Self {
  69. match level {
  70. OptimizationLevel::None => inkwell::OptimizationLevel::None,
  71. OptimizationLevel::Less => inkwell::OptimizationLevel::Less,
  72. OptimizationLevel::Default => inkwell::OptimizationLevel::Default,
  73. OptimizationLevel::Aggressive => inkwell::OptimizationLevel::Aggressive,
  74. }
  75. }
  76. }
  77. #[cfg(feature = "llvm")]
  78. impl From<inkwell::OptimizationLevel> for OptimizationLevel {
  79. fn from(level: inkwell::OptimizationLevel) -> Self {
  80. match level {
  81. inkwell::OptimizationLevel::None => OptimizationLevel::None,
  82. inkwell::OptimizationLevel::Less => OptimizationLevel::Less,
  83. inkwell::OptimizationLevel::Default => OptimizationLevel::Default,
  84. inkwell::OptimizationLevel::Aggressive => OptimizationLevel::Aggressive,
  85. }
  86. }
  87. }
  88. pub enum HostFunctions {
  89. PutContractData,
  90. GetContractData,
  91. HasContractData,
  92. ExtendContractDataTtl,
  93. ExtendCurrentContractInstanceAndCodeTtl,
  94. LogFromLinearMemory,
  95. SymbolNewFromLinearMemory,
  96. VectorNew,
  97. VectorNewFromLinearMemory,
  98. MapNewFromLinearMemory,
  99. Call,
  100. ObjToU64,
  101. ObjFromU64,
  102. ObjToI128Lo64,
  103. ObjToI128Hi64,
  104. ObjToU128Lo64,
  105. ObjToU128Hi64,
  106. ObjFromI128Pieces,
  107. ObjFromU128Pieces,
  108. RequireAuth,
  109. AuthAsCurrContract,
  110. MapNew,
  111. MapPut,
  112. VecPushBack,
  113. StringNewFromLinearMemory,
  114. StrKeyToAddr,
  115. GetCurrentContractAddress,
  116. }
  117. impl HostFunctions {
  118. pub fn name(&self) -> &str {
  119. match self {
  120. HostFunctions::PutContractData => "l._",
  121. HostFunctions::GetContractData => "l.1",
  122. HostFunctions::HasContractData => "l.0",
  123. HostFunctions::ExtendContractDataTtl => "l.7",
  124. HostFunctions::ExtendCurrentContractInstanceAndCodeTtl => "l.8",
  125. HostFunctions::LogFromLinearMemory => "x._",
  126. HostFunctions::SymbolNewFromLinearMemory => "b.j",
  127. HostFunctions::VectorNew => "v._",
  128. HostFunctions::VectorNewFromLinearMemory => "v.g",
  129. HostFunctions::Call => "d._",
  130. HostFunctions::ObjToU64 => "i.0",
  131. HostFunctions::ObjFromU64 => "i._",
  132. HostFunctions::ObjToI128Lo64 => "i.7",
  133. HostFunctions::ObjToI128Hi64 => "i.8",
  134. HostFunctions::ObjToU128Lo64 => "i.4",
  135. HostFunctions::ObjToU128Hi64 => "i.5",
  136. HostFunctions::ObjFromI128Pieces => "i.6",
  137. HostFunctions::ObjFromU128Pieces => "i.3",
  138. HostFunctions::RequireAuth => "a.0",
  139. HostFunctions::AuthAsCurrContract => "a.3",
  140. HostFunctions::MapNewFromLinearMemory => "m.9",
  141. HostFunctions::MapNew => "m._",
  142. HostFunctions::MapPut => "m.0",
  143. HostFunctions::VecPushBack => "v.6",
  144. HostFunctions::StringNewFromLinearMemory => "b.i",
  145. HostFunctions::StrKeyToAddr => "a.1",
  146. HostFunctions::GetCurrentContractAddress => "x.7",
  147. }
  148. }
  149. }
  150. #[derive(Clone, Debug, PartialEq)]
  151. pub struct Options {
  152. pub dead_storage: bool,
  153. pub constant_folding: bool,
  154. pub strength_reduce: bool,
  155. pub vector_to_slice: bool,
  156. pub common_subexpression_elimination: bool,
  157. pub generate_debug_information: bool,
  158. pub opt_level: OptimizationLevel,
  159. pub log_runtime_errors: bool,
  160. pub log_prints: bool,
  161. #[cfg(feature = "wasm_opt")]
  162. pub wasm_opt: Option<OptimizationPasses>,
  163. pub soroban_version: Option<u64>,
  164. }
  165. impl Default for Options {
  166. fn default() -> Self {
  167. Options {
  168. dead_storage: true,
  169. constant_folding: true,
  170. strength_reduce: true,
  171. vector_to_slice: true,
  172. common_subexpression_elimination: true,
  173. generate_debug_information: false,
  174. opt_level: OptimizationLevel::Default,
  175. log_runtime_errors: false,
  176. log_prints: true,
  177. #[cfg(feature = "wasm_opt")]
  178. wasm_opt: None,
  179. soroban_version: None,
  180. }
  181. }
  182. }
  183. /// The contracts are fully resolved but they do not have any CFGs which is needed for
  184. /// the llvm code emitter. This will also do additional code checks.
  185. pub fn codegen(ns: &mut Namespace, opt: &Options) {
  186. if ns.diagnostics.any_errors() {
  187. return;
  188. }
  189. let mut contracts_done = Vec::new();
  190. contracts_done.resize(ns.contracts.len(), false);
  191. // codegen all the contracts; some additional errors/warnings will be detected here
  192. while contracts_done.iter().any(|e| !*e) {
  193. for contract_no in 0..ns.contracts.len() {
  194. if contracts_done[contract_no] {
  195. continue;
  196. }
  197. if !ns.contracts[contract_no].instantiable {
  198. contracts_done[contract_no] = true;
  199. continue;
  200. }
  201. // does this contract create any contract which are not done
  202. if ns.contracts[contract_no]
  203. .creates
  204. .iter()
  205. .any(|c| !contracts_done[*c])
  206. {
  207. continue;
  208. }
  209. contract(contract_no, ns, opt);
  210. if ns.diagnostics.any_errors() {
  211. return;
  212. }
  213. contracts_done[contract_no] = true;
  214. }
  215. }
  216. if ns.target == Target::Solana {
  217. for contract_no in 0..ns.contracts.len() {
  218. if ns.contracts[contract_no].instantiable {
  219. let diag = collect_accounts_from_contract(contract_no, ns);
  220. ns.diagnostics.extend(diag);
  221. }
  222. }
  223. for contract_no in 0..ns.contracts.len() {
  224. if ns.contracts[contract_no].instantiable {
  225. manage_contract_accounts(contract_no, ns);
  226. }
  227. }
  228. }
  229. ns.diagnostics.sort_and_dedup();
  230. }
  231. fn contract(contract_no: usize, ns: &mut Namespace, opt: &Options) {
  232. if !ns.diagnostics.any_errors() && ns.contracts[contract_no].instantiable {
  233. layout(contract_no, ns);
  234. let mut cfg_no = 0;
  235. let mut all_cfg = Vec::new();
  236. // all the functions should have a cfg_no assigned, so we can generate call instructions to the correct function
  237. for (_, func_cfg) in ns.contracts[contract_no].all_functions.iter_mut() {
  238. *func_cfg = cfg_no;
  239. cfg_no += 1;
  240. }
  241. // create a cfg number for yul functions
  242. for yul_fn_no in &ns.contracts[contract_no].yul_functions {
  243. ns.yul_functions[*yul_fn_no].cfg_no = cfg_no;
  244. cfg_no += 1;
  245. }
  246. all_cfg.resize(cfg_no, ControlFlowGraph::placeholder());
  247. // clone all_functions so we can pass a mutable reference to generate_cfg
  248. for (function_no, cfg_no) in ns.contracts[contract_no]
  249. .all_functions
  250. .iter()
  251. .map(|(function_no, cfg_no)| (*function_no, *cfg_no))
  252. .collect::<Vec<(usize, usize)>>()
  253. .into_iter()
  254. {
  255. cfg::generate_cfg(
  256. contract_no,
  257. Some(function_no),
  258. cfg_no,
  259. &mut all_cfg,
  260. ns,
  261. opt,
  262. )
  263. }
  264. // generate the cfg for yul functions
  265. for yul_func_no in ns.contracts[contract_no].yul_functions.clone() {
  266. generate_yul_function_cfg(contract_no, yul_func_no, &mut all_cfg, ns, opt);
  267. }
  268. // Generate cfg for storage initializers
  269. let cfg = storage_initializer(contract_no, ns, opt);
  270. let pos = all_cfg.len();
  271. all_cfg.push(cfg);
  272. ns.contracts[contract_no].initializer = Some(pos);
  273. if ns.contracts[contract_no].constructors(ns).is_empty() {
  274. // generate the default constructor
  275. let func = ns.default_constructor(contract_no);
  276. let cfg_no = all_cfg.len();
  277. all_cfg.push(ControlFlowGraph::placeholder());
  278. cfg::generate_cfg(contract_no, None, cfg_no, &mut all_cfg, ns, opt);
  279. ns.contracts[contract_no].default_constructor = Some((func, cfg_no));
  280. }
  281. for mut dispatch_cfg in function_dispatch(contract_no, &mut all_cfg, ns, opt) {
  282. optimize_and_check_cfg(&mut dispatch_cfg, ns, ASTFunction::None, opt);
  283. all_cfg.push(dispatch_cfg);
  284. }
  285. ns.contracts[contract_no].cfg = all_cfg;
  286. }
  287. }
  288. /// This function will set all contract storage initializers and should be called from the constructor
  289. fn storage_initializer(contract_no: usize, ns: &mut Namespace, opt: &Options) -> ControlFlowGraph {
  290. // note the single `:` to prevent a name clash with user-declared functions
  291. let mut cfg = ControlFlowGraph::new(STORAGE_INITIALIZER.to_string(), ASTFunction::None);
  292. let mut vartab = Vartable::new(ns.next_id);
  293. for layout in &ns.contracts[contract_no].layout {
  294. let var = &ns.contracts[layout.contract_no].variables[layout.var_no];
  295. if let Some(init) = &var.initializer {
  296. let storage = ns.contracts[contract_no].get_storage_slot(
  297. pt::Loc::Codegen,
  298. layout.contract_no,
  299. layout.var_no,
  300. ns,
  301. None,
  302. );
  303. let mut value = expression(init, &mut cfg, contract_no, None, ns, &mut vartab, opt);
  304. if ns.target == Target::Soroban {
  305. value = soroban_encode_arg(value, &mut cfg, &mut vartab, ns);
  306. }
  307. cfg.add(
  308. &mut vartab,
  309. Instr::SetStorage {
  310. value,
  311. ty: var.ty.clone(),
  312. storage,
  313. storage_type: var.storage_type.clone(),
  314. },
  315. );
  316. }
  317. }
  318. cfg.add(&mut vartab, Instr::Return { value: Vec::new() });
  319. vartab.finalize(ns, &mut cfg);
  320. optimize_and_check_cfg(&mut cfg, ns, ASTFunction::None, opt);
  321. cfg
  322. }
  323. /// Layout the contract. We determine the layout of variables and deal with overriding variables
  324. fn layout(contract_no: usize, ns: &mut Namespace) {
  325. let mut slot = if ns.target == Target::Solana {
  326. BigInt::from(SOLANA_FIRST_OFFSET)
  327. } else {
  328. BigInt::zero()
  329. };
  330. for base_contract_no in ns.contract_bases(contract_no) {
  331. for var_no in 0..ns.contracts[base_contract_no].variables.len() {
  332. if !ns.contracts[base_contract_no].variables[var_no].constant {
  333. let ty = ns.contracts[base_contract_no].variables[var_no].ty.clone();
  334. if ns.target == Target::Solana {
  335. // elements need to be aligned on solana
  336. let alignment = ty.align_of(ns);
  337. let offset = slot.clone() % alignment;
  338. if offset > BigInt::zero() {
  339. slot += alignment - offset;
  340. }
  341. }
  342. ns.contracts[contract_no].layout.push(Layout {
  343. slot: slot.clone(),
  344. contract_no: base_contract_no,
  345. var_no,
  346. ty: ty.clone(),
  347. });
  348. slot += ty.storage_slots(ns);
  349. }
  350. }
  351. }
  352. let constructors = ns.contracts[contract_no].constructors(ns);
  353. if !constructors.is_empty() {
  354. if let Some((_, exp)) = &ns.functions[constructors[0]].annotations.space {
  355. // This code path is only reachable on Solana
  356. assert_eq!(ns.target, Target::Solana);
  357. if let Ok((_, value)) = eval_const_number(exp, ns, &mut Diagnostics::default()) {
  358. if slot > value {
  359. ns.diagnostics.push(Diagnostic::error(
  360. exp.loc(),
  361. format!("contract requires at least {} bytes of space", slot),
  362. ));
  363. } else if value > BigInt::from(MAXIMUM_ACCOUNT_SIZE) {
  364. ns.diagnostics.push(Diagnostic::error(
  365. exp.loc(),
  366. "Solana's runtime does not permit accounts larger than 10 MB".to_string(),
  367. ));
  368. }
  369. }
  370. }
  371. }
  372. ns.contracts[contract_no].fixed_layout_size = slot;
  373. }
  374. trait LLVMName {
  375. fn llvm_symbol(&self, ns: &Namespace) -> String;
  376. }
  377. impl LLVMName for Function {
  378. /// Return a unique string for this function which is a valid llvm symbol
  379. fn llvm_symbol(&self, ns: &Namespace) -> String {
  380. let mut sig = self.id.name.to_owned();
  381. if !self.params.is_empty() {
  382. sig.push_str("__");
  383. for (i, p) in self.params.iter().enumerate() {
  384. if i > 0 {
  385. sig.push('_');
  386. }
  387. sig.push_str(&p.ty.to_llvm_string(ns));
  388. }
  389. }
  390. sig
  391. }
  392. }
  393. #[derive(Clone, Debug, PartialEq, Eq)]
  394. pub enum Expression {
  395. Add {
  396. loc: pt::Loc,
  397. ty: Type,
  398. overflowing: bool,
  399. left: Box<Expression>,
  400. right: Box<Expression>,
  401. },
  402. AllocDynamicBytes {
  403. loc: pt::Loc,
  404. ty: Type,
  405. size: Box<Expression>,
  406. initializer: Option<Vec<u8>>,
  407. },
  408. ArrayLiteral {
  409. loc: pt::Loc,
  410. ty: Type,
  411. dimensions: Vec<u32>,
  412. values: Vec<Expression>,
  413. },
  414. BitwiseAnd {
  415. loc: pt::Loc,
  416. ty: Type,
  417. left: Box<Expression>,
  418. right: Box<Expression>,
  419. },
  420. BitwiseOr {
  421. loc: pt::Loc,
  422. ty: Type,
  423. left: Box<Expression>,
  424. right: Box<Expression>,
  425. },
  426. BitwiseXor {
  427. loc: pt::Loc,
  428. ty: Type,
  429. left: Box<Expression>,
  430. right: Box<Expression>,
  431. },
  432. BoolLiteral {
  433. loc: pt::Loc,
  434. value: bool,
  435. },
  436. Builtin {
  437. loc: pt::Loc,
  438. tys: Vec<Type>,
  439. kind: Builtin,
  440. args: Vec<Expression>,
  441. },
  442. BytesCast {
  443. loc: pt::Loc,
  444. ty: Type,
  445. from: Type,
  446. expr: Box<Expression>,
  447. },
  448. BytesLiteral {
  449. loc: pt::Loc,
  450. ty: Type,
  451. value: Vec<u8>,
  452. },
  453. Cast {
  454. loc: pt::Loc,
  455. ty: Type,
  456. expr: Box<Expression>,
  457. },
  458. BitwiseNot {
  459. loc: pt::Loc,
  460. ty: Type,
  461. expr: Box<Expression>,
  462. },
  463. ConstArrayLiteral {
  464. loc: pt::Loc,
  465. ty: Type,
  466. dimensions: Vec<u32>,
  467. values: Vec<Expression>,
  468. },
  469. UnsignedDivide {
  470. loc: pt::Loc,
  471. ty: Type,
  472. left: Box<Expression>,
  473. right: Box<Expression>,
  474. },
  475. SignedDivide {
  476. loc: pt::Loc,
  477. ty: Type,
  478. left: Box<Expression>,
  479. right: Box<Expression>,
  480. },
  481. Equal {
  482. loc: pt::Loc,
  483. left: Box<Expression>,
  484. right: Box<Expression>,
  485. },
  486. FormatString {
  487. loc: pt::Loc,
  488. args: Vec<(FormatArg, Expression)>,
  489. },
  490. FunctionArg {
  491. loc: pt::Loc,
  492. ty: Type,
  493. arg_no: usize,
  494. },
  495. GetRef {
  496. loc: pt::Loc,
  497. ty: Type,
  498. expr: Box<Expression>,
  499. },
  500. InternalFunctionCfg {
  501. ty: Type,
  502. cfg_no: usize,
  503. },
  504. Keccak256 {
  505. loc: pt::Loc,
  506. ty: Type,
  507. exprs: Vec<Expression>,
  508. },
  509. Less {
  510. loc: pt::Loc,
  511. signed: bool,
  512. left: Box<Expression>,
  513. right: Box<Expression>,
  514. },
  515. LessEqual {
  516. loc: pt::Loc,
  517. signed: bool,
  518. left: Box<Expression>,
  519. right: Box<Expression>,
  520. },
  521. Load {
  522. loc: pt::Loc,
  523. ty: Type,
  524. expr: Box<Expression>,
  525. },
  526. UnsignedModulo {
  527. loc: pt::Loc,
  528. ty: Type,
  529. left: Box<Expression>,
  530. right: Box<Expression>,
  531. },
  532. SignedModulo {
  533. loc: pt::Loc,
  534. ty: Type,
  535. left: Box<Expression>,
  536. right: Box<Expression>,
  537. },
  538. More {
  539. loc: pt::Loc,
  540. signed: bool,
  541. left: Box<Expression>,
  542. right: Box<Expression>,
  543. },
  544. MoreEqual {
  545. loc: pt::Loc,
  546. signed: bool,
  547. left: Box<Expression>,
  548. right: Box<Expression>,
  549. },
  550. Multiply {
  551. loc: pt::Loc,
  552. ty: Type,
  553. overflowing: bool,
  554. left: Box<Expression>,
  555. right: Box<Expression>,
  556. },
  557. Not {
  558. loc: pt::Loc,
  559. expr: Box<Expression>,
  560. },
  561. NotEqual {
  562. loc: pt::Loc,
  563. left: Box<Expression>,
  564. right: Box<Expression>,
  565. },
  566. NumberLiteral {
  567. loc: pt::Loc,
  568. ty: Type,
  569. value: BigInt,
  570. },
  571. Poison,
  572. Power {
  573. loc: pt::Loc,
  574. ty: Type,
  575. overflowing: bool,
  576. base: Box<Expression>,
  577. exp: Box<Expression>,
  578. },
  579. RationalNumberLiteral {
  580. loc: pt::Loc,
  581. ty: Type,
  582. rational: BigRational,
  583. },
  584. ReturnData {
  585. loc: pt::Loc,
  586. },
  587. SignExt {
  588. loc: pt::Loc,
  589. ty: Type,
  590. expr: Box<Expression>,
  591. },
  592. ShiftLeft {
  593. loc: pt::Loc,
  594. ty: Type,
  595. left: Box<Expression>,
  596. right: Box<Expression>,
  597. },
  598. ShiftRight {
  599. loc: pt::Loc,
  600. ty: Type,
  601. left: Box<Expression>,
  602. right: Box<Expression>,
  603. signed: bool,
  604. },
  605. StorageArrayLength {
  606. loc: pt::Loc,
  607. ty: Type,
  608. array: Box<Expression>,
  609. elem_ty: Type,
  610. },
  611. StringCompare {
  612. loc: pt::Loc,
  613. left: StringLocation<Expression>,
  614. right: StringLocation<Expression>,
  615. },
  616. StructLiteral {
  617. loc: pt::Loc,
  618. ty: Type,
  619. values: Vec<Expression>,
  620. },
  621. StructMember {
  622. loc: pt::Loc,
  623. ty: Type,
  624. expr: Box<Expression>,
  625. member: usize,
  626. },
  627. Subscript {
  628. loc: pt::Loc,
  629. ty: Type,
  630. array_ty: Type,
  631. expr: Box<Expression>,
  632. index: Box<Expression>,
  633. },
  634. Subtract {
  635. loc: pt::Loc,
  636. ty: Type,
  637. overflowing: bool,
  638. left: Box<Expression>,
  639. right: Box<Expression>,
  640. },
  641. Trunc {
  642. loc: pt::Loc,
  643. ty: Type,
  644. expr: Box<Expression>,
  645. },
  646. Negate {
  647. loc: pt::Loc,
  648. ty: Type,
  649. overflowing: bool,
  650. expr: Box<Expression>,
  651. },
  652. Undefined {
  653. ty: Type,
  654. },
  655. Variable {
  656. loc: pt::Loc,
  657. ty: Type,
  658. var_no: usize,
  659. },
  660. ZeroExt {
  661. loc: pt::Loc,
  662. ty: Type,
  663. expr: Box<Expression>,
  664. },
  665. AdvancePointer {
  666. pointer: Box<Expression>,
  667. bytes_offset: Box<Expression>,
  668. },
  669. VectorData {
  670. pointer: Box<Expression>,
  671. },
  672. }
  673. impl CodeLocation for Expression {
  674. fn loc(&self) -> pt::Loc {
  675. match self {
  676. Expression::StorageArrayLength { loc, .. }
  677. | Expression::Builtin { loc, .. }
  678. | Expression::Cast { loc, .. }
  679. | Expression::NumberLiteral { loc, .. }
  680. | Expression::Keccak256 { loc, .. }
  681. | Expression::MoreEqual { loc, .. }
  682. | Expression::ReturnData { loc }
  683. | Expression::Subscript { loc, .. }
  684. | Expression::Trunc { loc, .. }
  685. | Expression::Variable { loc, .. }
  686. | Expression::SignExt { loc, .. }
  687. | Expression::GetRef { loc, .. }
  688. | Expression::Load { loc, .. }
  689. | Expression::BytesLiteral { loc, .. }
  690. | Expression::Add { loc, .. }
  691. | Expression::Multiply { loc, .. }
  692. | Expression::Subtract { loc, .. }
  693. | Expression::FormatString { loc, .. }
  694. | Expression::LessEqual { loc, .. }
  695. | Expression::BoolLiteral { loc, .. }
  696. | Expression::UnsignedDivide { loc, .. }
  697. | Expression::SignedDivide { loc, .. }
  698. | Expression::UnsignedModulo { loc, .. }
  699. | Expression::SignedModulo { loc, .. }
  700. | Expression::Power { loc, .. }
  701. | Expression::BitwiseOr { loc, .. }
  702. | Expression::BitwiseAnd { loc, .. }
  703. | Expression::BitwiseXor { loc, .. }
  704. | Expression::Equal { loc, .. }
  705. | Expression::NotEqual { loc, .. }
  706. | Expression::BitwiseNot { loc, .. }
  707. | Expression::Negate { loc, .. }
  708. | Expression::Less { loc, .. }
  709. | Expression::Not { loc, .. }
  710. | Expression::StructLiteral { loc, .. }
  711. | Expression::ArrayLiteral { loc, .. }
  712. | Expression::ConstArrayLiteral { loc, .. }
  713. | Expression::StructMember { loc, .. }
  714. | Expression::StringCompare { loc, .. }
  715. | Expression::FunctionArg { loc, .. }
  716. | Expression::ShiftRight { loc, .. }
  717. | Expression::ShiftLeft { loc, .. }
  718. | Expression::RationalNumberLiteral { loc, .. }
  719. | Expression::AllocDynamicBytes { loc, .. }
  720. | Expression::BytesCast { loc, .. }
  721. | Expression::More { loc, .. }
  722. | Expression::ZeroExt { loc, .. } => *loc,
  723. Expression::InternalFunctionCfg { .. }
  724. | Expression::Poison
  725. | Expression::Undefined { .. }
  726. | Expression::AdvancePointer { .. }
  727. | Expression::VectorData { .. } => pt::Loc::Codegen,
  728. }
  729. }
  730. }
  731. impl Recurse for Expression {
  732. type ArgType = Expression;
  733. fn recurse<T>(&self, cx: &mut T, f: fn(expr: &Expression, ctx: &mut T) -> bool) {
  734. if !f(self, cx) {
  735. return;
  736. }
  737. match self {
  738. Expression::BitwiseAnd { left, right, .. }
  739. | Expression::BitwiseOr { left, right, .. }
  740. | Expression::UnsignedDivide { left, right, .. }
  741. | Expression::SignedDivide { left, right, .. }
  742. | Expression::Equal { left, right, .. }
  743. | Expression::Less { left, right, .. }
  744. | Expression::LessEqual { left, right, .. }
  745. | Expression::BitwiseXor { left, right, .. }
  746. | Expression::More { left, right, .. }
  747. | Expression::MoreEqual { left, right, .. }
  748. | Expression::Multiply { left, right, .. }
  749. | Expression::NotEqual { left, right, .. }
  750. | Expression::ShiftLeft { left, right, .. }
  751. | Expression::ShiftRight { left, right, .. }
  752. | Expression::Power {
  753. base: left,
  754. exp: right,
  755. ..
  756. }
  757. | Expression::Subscript {
  758. expr: left,
  759. index: right,
  760. ..
  761. }
  762. | Expression::Subtract { left, right, .. }
  763. | Expression::AdvancePointer {
  764. pointer: left,
  765. bytes_offset: right,
  766. ..
  767. }
  768. | Expression::Add { left, right, .. } => {
  769. left.recurse(cx, f);
  770. right.recurse(cx, f);
  771. }
  772. Expression::BytesCast { expr, .. }
  773. | Expression::Cast { expr, .. }
  774. | Expression::GetRef { expr, .. }
  775. | Expression::Not { expr, .. }
  776. | Expression::Trunc { expr, .. }
  777. | Expression::Negate { expr, .. }
  778. | Expression::ZeroExt { expr, .. }
  779. | Expression::SignExt { expr, .. }
  780. | Expression::BitwiseNot { expr, .. }
  781. | Expression::Load { expr, .. }
  782. | Expression::StorageArrayLength { array: expr, .. }
  783. | Expression::StructMember { expr, .. }
  784. | Expression::AllocDynamicBytes { size: expr, .. } => {
  785. expr.recurse(cx, f);
  786. }
  787. Expression::Builtin { args, .. }
  788. | Expression::ConstArrayLiteral { values: args, .. }
  789. | Expression::Keccak256 { exprs: args, .. }
  790. | Expression::StructLiteral { values: args, .. }
  791. | Expression::ArrayLiteral { values: args, .. } => {
  792. for item in args {
  793. item.recurse(cx, f);
  794. }
  795. }
  796. Expression::FormatString { args, .. } => {
  797. for item in args {
  798. item.1.recurse(cx, f);
  799. }
  800. }
  801. Expression::StringCompare { left, right, .. } => {
  802. if let StringLocation::RunTime(exp) = left {
  803. exp.recurse(cx, f);
  804. }
  805. if let StringLocation::RunTime(exp) = right {
  806. exp.recurse(cx, f);
  807. }
  808. }
  809. _ => (),
  810. }
  811. }
  812. }
  813. impl RetrieveType for Expression {
  814. fn ty(&self) -> Type {
  815. match self {
  816. Expression::ReturnData { loc: _ } => Type::DynamicBytes,
  817. Expression::Builtin { tys, .. } => {
  818. assert_eq!(tys.len(), 1);
  819. tys[0].clone()
  820. }
  821. Expression::Keccak256 { ty, .. }
  822. | Expression::Undefined { ty }
  823. | Expression::Variable { ty, .. }
  824. | Expression::Trunc { ty, .. }
  825. | Expression::ZeroExt { ty, .. }
  826. | Expression::Cast { ty, .. }
  827. | Expression::SignExt { ty, .. }
  828. | Expression::GetRef { ty, .. }
  829. | Expression::Load { ty, .. }
  830. | Expression::BytesLiteral { ty, .. }
  831. | Expression::Add { ty, .. }
  832. | Expression::NumberLiteral { ty, .. }
  833. | Expression::Multiply { ty, .. }
  834. | Expression::Subtract { ty, .. }
  835. | Expression::SignedDivide { ty, .. }
  836. | Expression::UnsignedDivide { ty, .. }
  837. | Expression::SignedModulo { ty, .. }
  838. | Expression::UnsignedModulo { ty, .. }
  839. | Expression::Power { ty, .. }
  840. | Expression::BitwiseOr { ty, .. }
  841. | Expression::BitwiseAnd { ty, .. }
  842. | Expression::BitwiseXor { ty, .. }
  843. | Expression::ShiftLeft { ty, .. }
  844. | Expression::ShiftRight { ty, .. }
  845. | Expression::BitwiseNot { ty, .. }
  846. | Expression::StorageArrayLength { ty, .. }
  847. | Expression::Negate { ty, .. }
  848. | Expression::StructLiteral { ty, .. }
  849. | Expression::ArrayLiteral { ty, .. }
  850. | Expression::ConstArrayLiteral { ty, .. }
  851. | Expression::StructMember { ty, .. }
  852. | Expression::FunctionArg { ty, .. }
  853. | Expression::AllocDynamicBytes { ty, .. }
  854. | Expression::BytesCast { ty, .. }
  855. | Expression::RationalNumberLiteral { ty, .. }
  856. | Expression::Subscript { ty, .. }
  857. | Expression::InternalFunctionCfg { ty, .. } => ty.clone(),
  858. Expression::BoolLiteral { .. }
  859. | Expression::MoreEqual { .. }
  860. | Expression::More { .. }
  861. | Expression::Not { .. }
  862. | Expression::NotEqual { .. }
  863. | Expression::Less { .. }
  864. | Expression::Equal { .. }
  865. | Expression::StringCompare { .. }
  866. | Expression::LessEqual { .. } => Type::Bool,
  867. Expression::AdvancePointer { .. } => Type::BufferPointer,
  868. Expression::FormatString { .. } => Type::String,
  869. Expression::VectorData { .. } => Type::Uint(64),
  870. Expression::Poison => unreachable!("Expression does not have a type"),
  871. }
  872. }
  873. }
  874. impl Expression {
  875. /// Increment an expression by some value.
  876. pub(crate) fn add_u32(self, other: Expression) -> Self {
  877. Expression::Add {
  878. loc: pt::Loc::Codegen,
  879. ty: Type::Uint(32),
  880. overflowing: false,
  881. left: self.into(),
  882. right: other.into(),
  883. }
  884. }
  885. pub(crate) fn cast(&self, to: &Type, ns: &Namespace) -> Expression {
  886. let from = self.ty();
  887. if &from == to {
  888. return self.clone();
  889. }
  890. let address_bits = ns.address_length as u16 * 8;
  891. // When converting from literals, there is not need to trunc or extend.
  892. match (self, &from, to) {
  893. (Expression::NumberLiteral { value, .. }, p, &Type::Uint(to_len))
  894. if p.is_primitive() =>
  895. {
  896. return if value.sign() == Sign::Minus {
  897. let mut bs = value.to_signed_bytes_le();
  898. bs.resize(to_len as usize / 8, 0xff);
  899. Expression::NumberLiteral {
  900. loc: self.loc(),
  901. ty: Type::Uint(to_len),
  902. value: BigInt::from_bytes_le(Sign::Plus, &bs),
  903. }
  904. } else {
  905. Expression::NumberLiteral {
  906. loc: self.loc(),
  907. ty: Type::Uint(to_len),
  908. value: value.clone(),
  909. }
  910. }
  911. }
  912. (Expression::NumberLiteral { value, .. }, p, &Type::Int(to_len))
  913. if p.is_primitive() =>
  914. {
  915. return Expression::NumberLiteral {
  916. loc: self.loc(),
  917. ty: Type::Int(to_len),
  918. value: value.clone(),
  919. };
  920. }
  921. (Expression::NumberLiteral { value, .. }, p, &Type::Bytes(to_len))
  922. if p.is_primitive() =>
  923. {
  924. return Expression::NumberLiteral {
  925. loc: self.loc(),
  926. ty: Type::Bytes(to_len),
  927. value: value.clone(),
  928. };
  929. }
  930. (Expression::NumberLiteral { value, .. }, p, &Type::Address(payable))
  931. if p.is_primitive() =>
  932. {
  933. return Expression::NumberLiteral {
  934. loc: self.loc(),
  935. ty: Type::Address(payable),
  936. value: value.clone(),
  937. };
  938. }
  939. (Expression::BytesLiteral { value: bs, .. }, p, &Type::Bytes(to_len))
  940. if p.is_primitive() =>
  941. {
  942. let mut bs = bs.to_owned();
  943. bs.resize(to_len as usize, 0);
  944. return Expression::BytesLiteral {
  945. loc: self.loc(),
  946. ty: Type::Bytes(to_len),
  947. value: bs,
  948. };
  949. }
  950. (
  951. Expression::BytesLiteral {
  952. loc, value: init, ..
  953. },
  954. _,
  955. &Type::DynamicBytes,
  956. )
  957. | (
  958. Expression::BytesLiteral {
  959. loc, value: init, ..
  960. },
  961. _,
  962. &Type::String,
  963. ) => {
  964. return Expression::AllocDynamicBytes {
  965. loc: *loc,
  966. ty: to.clone(),
  967. size: Box::new(Expression::NumberLiteral {
  968. loc: *loc,
  969. ty: Type::Uint(32),
  970. value: BigInt::from(init.len()),
  971. }),
  972. initializer: Some(init.clone()),
  973. };
  974. }
  975. (Expression::NumberLiteral { value, .. }, _, &Type::Rational) => {
  976. return Expression::RationalNumberLiteral {
  977. loc: self.loc(),
  978. ty: Type::Rational,
  979. rational: BigRational::from(value.clone()),
  980. };
  981. }
  982. _ => (),
  983. }
  984. let from = match (&from, to) {
  985. (Type::Enum(enum_no), Type::Uint(_)) | (Type::Enum(enum_no), Type::Int(_)) => {
  986. let enum_ty = &ns.enums[*enum_no];
  987. let from_width = enum_ty.ty.bits(ns);
  988. Type::Uint(from_width)
  989. }
  990. (Type::Value, Type::Uint(_)) | (Type::Value, Type::Int(_)) => {
  991. let from_len = (ns.value_length as u16) * 8;
  992. Type::Int(from_len)
  993. }
  994. _ => from,
  995. };
  996. match (&from, to) {
  997. (Type::Uint(from_width), Type::Enum(enum_no))
  998. | (Type::Int(from_width), Type::Enum(enum_no)) => {
  999. let enum_ty = &ns.enums[*enum_no];
  1000. // Not checking eval const number
  1001. let to_width = enum_ty.ty.bits(ns);
  1002. match from_width.cmp(&to_width) {
  1003. Ordering::Greater => Expression::Trunc {
  1004. loc: self.loc(),
  1005. ty: to.clone(),
  1006. expr: Box::new(self.clone()),
  1007. },
  1008. Ordering::Less => Expression::ZeroExt {
  1009. loc: self.loc(),
  1010. ty: to.clone(),
  1011. expr: Box::new(self.clone()),
  1012. },
  1013. Ordering::Equal => Expression::Cast {
  1014. loc: self.loc(),
  1015. ty: to.clone(),
  1016. expr: Box::new(self.clone()),
  1017. },
  1018. }
  1019. }
  1020. (Type::Bytes(1), Type::Uint(8)) | (Type::Uint(8), Type::Bytes(1)) => self.clone(),
  1021. (Type::Uint(from_len), Type::Uint(to_len))
  1022. | (Type::Uint(from_len), Type::Int(to_len)) => match from_len.cmp(to_len) {
  1023. Ordering::Greater => Expression::Trunc {
  1024. loc: self.loc(),
  1025. ty: to.clone(),
  1026. expr: Box::new(self.clone()),
  1027. },
  1028. Ordering::Less => Expression::ZeroExt {
  1029. loc: self.loc(),
  1030. ty: to.clone(),
  1031. expr: Box::new(self.clone()),
  1032. },
  1033. Ordering::Equal => Expression::Cast {
  1034. loc: self.loc(),
  1035. ty: to.clone(),
  1036. expr: Box::new(self.clone()),
  1037. },
  1038. },
  1039. (Type::Int(from_len), Type::Uint(to_len))
  1040. | (Type::Int(from_len), Type::Int(to_len)) => match from_len.cmp(to_len) {
  1041. Ordering::Greater => Expression::Trunc {
  1042. loc: self.loc(),
  1043. ty: to.clone(),
  1044. expr: Box::new(self.clone()),
  1045. },
  1046. Ordering::Less => Expression::SignExt {
  1047. loc: self.loc(),
  1048. ty: to.clone(),
  1049. expr: Box::new(self.clone()),
  1050. },
  1051. Ordering::Equal => Expression::Cast {
  1052. loc: self.loc(),
  1053. ty: to.clone(),
  1054. expr: Box::new(self.clone()),
  1055. },
  1056. },
  1057. (Type::Uint(from_len), Type::Address(_)) | (Type::Int(from_len), Type::Address(_)) => {
  1058. let address_to_int = if from.is_signed_int(ns) {
  1059. Type::Int(address_bits)
  1060. } else {
  1061. Type::Uint(address_bits)
  1062. };
  1063. let expr = match from_len.cmp(&address_bits) {
  1064. Ordering::Greater => Expression::Trunc {
  1065. loc: self.loc(),
  1066. ty: address_to_int,
  1067. expr: Box::new(self.clone()),
  1068. },
  1069. Ordering::Less if from.is_signed_int(ns) => Expression::ZeroExt {
  1070. loc: self.loc(),
  1071. ty: to.clone(),
  1072. expr: Box::new(self.clone()),
  1073. },
  1074. Ordering::Less => Expression::SignExt {
  1075. loc: self.loc(),
  1076. ty: to.clone(),
  1077. expr: Box::new(self.clone()),
  1078. },
  1079. Ordering::Equal => self.clone(),
  1080. };
  1081. Expression::Cast {
  1082. loc: self.loc(),
  1083. ty: to.clone(),
  1084. expr: Box::new(expr),
  1085. }
  1086. }
  1087. (Type::Address(_), Type::Uint(to_len)) | (Type::Address(_), Type::Int(to_len)) => {
  1088. let address_to_int = if to.is_signed_int(ns) {
  1089. Type::Int(address_bits)
  1090. } else {
  1091. Type::Uint(address_bits)
  1092. };
  1093. let expr = Expression::Cast {
  1094. loc: self.loc(),
  1095. ty: address_to_int,
  1096. expr: Box::new(self.clone()),
  1097. };
  1098. // now resize int to request size with sign extension etc
  1099. match to_len.cmp(&address_bits) {
  1100. Ordering::Less => Expression::Trunc {
  1101. loc: self.loc(),
  1102. ty: to.clone(),
  1103. expr: Box::new(expr),
  1104. },
  1105. Ordering::Greater if to.is_signed_int(ns) => Expression::ZeroExt {
  1106. loc: self.loc(),
  1107. ty: to.clone(),
  1108. expr: Box::new(expr),
  1109. },
  1110. Ordering::Greater => Expression::SignExt {
  1111. loc: self.loc(),
  1112. ty: to.clone(),
  1113. expr: Box::new(expr),
  1114. },
  1115. Ordering::Equal => expr,
  1116. }
  1117. }
  1118. (Type::Bytes(from_len), Type::Bytes(to_len)) => {
  1119. if to_len > from_len {
  1120. let shift = (to_len - from_len) * 8;
  1121. Expression::ShiftLeft {
  1122. loc: self.loc(),
  1123. ty: to.clone(),
  1124. left: Box::new(Expression::ZeroExt {
  1125. loc: self.loc(),
  1126. ty: to.clone(),
  1127. expr: Box::new(self.clone()),
  1128. }),
  1129. right: Box::new(Expression::NumberLiteral {
  1130. loc: self.loc(),
  1131. ty: Type::Uint(*to_len as u16 * 8),
  1132. value: BigInt::from_u8(shift).unwrap(),
  1133. }),
  1134. }
  1135. } else {
  1136. let shift = (from_len - to_len) * 8;
  1137. Expression::Trunc {
  1138. loc: self.loc(),
  1139. ty: to.clone(),
  1140. expr: Box::new(Expression::ShiftRight {
  1141. loc: self.loc(),
  1142. ty: from.clone(),
  1143. left: Box::new(self.clone()),
  1144. right: Box::new(Expression::NumberLiteral {
  1145. loc: self.loc(),
  1146. ty: Type::Uint(*from_len as u16 * 8),
  1147. value: BigInt::from_u8(shift).unwrap(),
  1148. }),
  1149. signed: false,
  1150. }),
  1151. }
  1152. }
  1153. }
  1154. // Conversion from rational will never happen in codegen
  1155. (Type::Uint(_) | Type::Int(_) | Type::Value, Type::Rational) => Expression::Cast {
  1156. loc: self.loc(),
  1157. ty: to.clone(),
  1158. expr: Box::new(self.clone()),
  1159. },
  1160. (Type::Bytes(_), Type::DynamicBytes) | (Type::DynamicBytes, Type::Bytes(_)) => {
  1161. Expression::BytesCast {
  1162. loc: self.loc(),
  1163. ty: from.clone(),
  1164. from: to.clone(),
  1165. expr: Box::new(self.clone()),
  1166. }
  1167. }
  1168. (Type::Bool, Type::Int(_) | Type::Uint(_)) => Expression::Cast {
  1169. loc: self.loc(),
  1170. ty: to.clone(),
  1171. expr: Box::new(self.clone()),
  1172. },
  1173. (Type::Int(_) | Type::Uint(_), Type::Bool) => Expression::NotEqual {
  1174. loc: self.loc(),
  1175. left: Box::new(Expression::NumberLiteral {
  1176. loc: self.loc(),
  1177. ty: self.ty(),
  1178. value: BigInt::zero(),
  1179. }),
  1180. right: Box::new(self.clone()),
  1181. },
  1182. (Type::Bytes(n), Type::Uint(bits) | Type::Int(bits)) => {
  1183. let num_bytes = (bits / 8) as u8;
  1184. match n.cmp(&num_bytes) {
  1185. Ordering::Greater => Expression::Trunc {
  1186. loc: self.loc(),
  1187. ty: to.clone(),
  1188. expr: Box::new(self.clone()),
  1189. },
  1190. Ordering::Less => Expression::ZeroExt {
  1191. loc: self.loc(),
  1192. ty: to.clone(),
  1193. expr: Box::new(self.clone()),
  1194. },
  1195. Ordering::Equal => Expression::Cast {
  1196. loc: self.loc(),
  1197. ty: to.clone(),
  1198. expr: Box::new(self.clone()),
  1199. },
  1200. }
  1201. }
  1202. (Type::FunctionSelector, _) => Expression::Cast {
  1203. loc: self.loc(),
  1204. ty: Type::Bytes(ns.target.selector_length()),
  1205. expr: self.clone().into(),
  1206. }
  1207. .cast(to, ns),
  1208. (_, Type::FunctionSelector) => self.cast(&Type::Bytes(ns.target.selector_length()), ns),
  1209. (Type::Uint(_), Type::Bytes(_))
  1210. | (Type::Int(_), Type::Bytes(_))
  1211. | (Type::Bytes(_), Type::Address(_))
  1212. | (Type::Address(false), Type::Address(true))
  1213. | (Type::Address(_), Type::Contract(_))
  1214. | (Type::Contract(_), Type::Address(_))
  1215. | (Type::Contract(_), Type::Contract(_))
  1216. | (Type::Address(true), Type::Address(false))
  1217. | (Type::Address(_), Type::Bytes(_))
  1218. | (Type::String, Type::DynamicBytes)
  1219. | (Type::DynamicBytes, Type::String)
  1220. | (Type::InternalFunction { .. }, Type::InternalFunction { .. })
  1221. | (Type::ExternalFunction { .. }, Type::ExternalFunction { .. }) => Expression::Cast {
  1222. loc: self.loc(),
  1223. ty: to.clone(),
  1224. expr: Box::new(self.clone()),
  1225. },
  1226. _ if !from.is_contract_storage()
  1227. && !to.is_contract_storage()
  1228. && from.is_reference_type(ns)
  1229. && !to.is_reference_type(ns) =>
  1230. {
  1231. let expr = Expression::Cast {
  1232. loc: self.loc(),
  1233. ty: Type::Uint(ns.target.ptr_size()),
  1234. expr: self.clone().into(),
  1235. };
  1236. expr.cast(to, ns)
  1237. }
  1238. _ if !from.is_contract_storage()
  1239. && !to.is_contract_storage()
  1240. && !from.is_reference_type(ns)
  1241. && to.is_reference_type(ns) =>
  1242. {
  1243. // cast non-pointer to pointer
  1244. let ptr_ty = Type::Uint(ns.target.ptr_size());
  1245. Expression::Cast {
  1246. loc: self.loc(),
  1247. ty: to.clone(),
  1248. expr: self.cast(&ptr_ty, ns).into(),
  1249. }
  1250. }
  1251. _ if !from.is_contract_storage()
  1252. && !to.is_contract_storage()
  1253. && !from.is_reference_type(ns)
  1254. && !to.is_reference_type(ns) =>
  1255. {
  1256. // cast pointer to different pointer
  1257. Expression::Cast {
  1258. loc: self.loc(),
  1259. ty: to.clone(),
  1260. expr: self.clone().into(),
  1261. }
  1262. }
  1263. _ => self.clone(),
  1264. }
  1265. }
  1266. /// Recurse over expression and copy each element through a filter. This allows the optimizer passes to create
  1267. /// copies of expressions while modifying the results slightly
  1268. #[must_use]
  1269. pub fn copy_filter<T, F>(&self, ctx: &mut T, filter: F) -> Expression
  1270. where
  1271. F: Fn(&Expression, &mut T) -> Expression,
  1272. {
  1273. filter(
  1274. &match self {
  1275. Expression::StructLiteral { loc, ty, values } => Expression::StructLiteral {
  1276. loc: *loc,
  1277. ty: ty.clone(),
  1278. values: values.iter().map(|e| filter(e, ctx)).collect(),
  1279. },
  1280. Expression::ArrayLiteral {
  1281. loc,
  1282. ty,
  1283. dimensions,
  1284. values,
  1285. } => Expression::ArrayLiteral {
  1286. loc: *loc,
  1287. ty: ty.clone(),
  1288. dimensions: dimensions.clone(),
  1289. values: values.iter().map(|e| filter(e, ctx)).collect(),
  1290. },
  1291. Expression::ConstArrayLiteral {
  1292. loc,
  1293. ty,
  1294. dimensions,
  1295. values,
  1296. } => Expression::ConstArrayLiteral {
  1297. loc: *loc,
  1298. ty: ty.clone(),
  1299. dimensions: dimensions.clone(),
  1300. values: values.iter().map(|e| filter(e, ctx)).collect(),
  1301. },
  1302. Expression::Add {
  1303. loc,
  1304. ty,
  1305. overflowing,
  1306. left,
  1307. right,
  1308. } => Expression::Add {
  1309. loc: *loc,
  1310. ty: ty.clone(),
  1311. overflowing: *overflowing,
  1312. left: Box::new(filter(left, ctx)),
  1313. right: Box::new(filter(right, ctx)),
  1314. },
  1315. Expression::Subtract {
  1316. loc,
  1317. ty,
  1318. overflowing,
  1319. left,
  1320. right,
  1321. } => Expression::Subtract {
  1322. loc: *loc,
  1323. ty: ty.clone(),
  1324. overflowing: *overflowing,
  1325. left: Box::new(filter(left, ctx)),
  1326. right: Box::new(filter(right, ctx)),
  1327. },
  1328. Expression::Multiply {
  1329. loc,
  1330. ty,
  1331. overflowing,
  1332. left,
  1333. right,
  1334. } => Expression::Multiply {
  1335. loc: *loc,
  1336. ty: ty.clone(),
  1337. overflowing: *overflowing,
  1338. left: Box::new(filter(left, ctx)),
  1339. right: Box::new(filter(right, ctx)),
  1340. },
  1341. Expression::UnsignedDivide {
  1342. loc,
  1343. ty,
  1344. left,
  1345. right,
  1346. } => Expression::UnsignedDivide {
  1347. loc: *loc,
  1348. ty: ty.clone(),
  1349. left: Box::new(filter(left, ctx)),
  1350. right: Box::new(filter(right, ctx)),
  1351. },
  1352. Expression::SignedDivide {
  1353. loc,
  1354. ty,
  1355. left,
  1356. right,
  1357. } => Expression::SignedDivide {
  1358. loc: *loc,
  1359. ty: ty.clone(),
  1360. left: Box::new(filter(left, ctx)),
  1361. right: Box::new(filter(right, ctx)),
  1362. },
  1363. Expression::Power {
  1364. loc,
  1365. ty,
  1366. overflowing,
  1367. base,
  1368. exp,
  1369. } => Expression::Power {
  1370. loc: *loc,
  1371. ty: ty.clone(),
  1372. overflowing: *overflowing,
  1373. base: Box::new(filter(base, ctx)),
  1374. exp: Box::new(filter(exp, ctx)),
  1375. },
  1376. Expression::BitwiseOr {
  1377. loc,
  1378. ty,
  1379. left,
  1380. right,
  1381. } => Expression::BitwiseOr {
  1382. loc: *loc,
  1383. ty: ty.clone(),
  1384. left: Box::new(filter(left, ctx)),
  1385. right: Box::new(filter(right, ctx)),
  1386. },
  1387. Expression::BitwiseAnd {
  1388. loc,
  1389. ty,
  1390. left,
  1391. right,
  1392. } => Expression::BitwiseAnd {
  1393. loc: *loc,
  1394. ty: ty.clone(),
  1395. left: Box::new(filter(left, ctx)),
  1396. right: Box::new(filter(right, ctx)),
  1397. },
  1398. Expression::BitwiseXor {
  1399. loc,
  1400. ty,
  1401. left,
  1402. right,
  1403. } => Expression::BitwiseXor {
  1404. loc: *loc,
  1405. ty: ty.clone(),
  1406. left: Box::new(filter(left, ctx)),
  1407. right: Box::new(filter(right, ctx)),
  1408. },
  1409. Expression::ShiftLeft {
  1410. loc,
  1411. ty,
  1412. left,
  1413. right,
  1414. } => Expression::ShiftLeft {
  1415. loc: *loc,
  1416. ty: ty.clone(),
  1417. left: Box::new(filter(left, ctx)),
  1418. right: Box::new(filter(right, ctx)),
  1419. },
  1420. Expression::ShiftRight {
  1421. loc,
  1422. ty,
  1423. left,
  1424. right,
  1425. signed: sign_extend,
  1426. } => Expression::ShiftRight {
  1427. loc: *loc,
  1428. ty: ty.clone(),
  1429. left: Box::new(filter(left, ctx)),
  1430. right: Box::new(filter(right, ctx)),
  1431. signed: *sign_extend,
  1432. },
  1433. Expression::Load { loc, ty, expr } => Expression::Load {
  1434. loc: *loc,
  1435. ty: ty.clone(),
  1436. expr: Box::new(filter(expr, ctx)),
  1437. },
  1438. Expression::ZeroExt { loc, ty, expr } => Expression::ZeroExt {
  1439. loc: *loc,
  1440. ty: ty.clone(),
  1441. expr: Box::new(filter(expr, ctx)),
  1442. },
  1443. Expression::SignExt { loc, ty, expr } => Expression::SignExt {
  1444. loc: *loc,
  1445. ty: ty.clone(),
  1446. expr: Box::new(filter(expr, ctx)),
  1447. },
  1448. Expression::Trunc { loc, ty, expr } => Expression::Trunc {
  1449. loc: *loc,
  1450. ty: ty.clone(),
  1451. expr: Box::new(filter(expr, ctx)),
  1452. },
  1453. Expression::Cast { loc, ty, expr } => Expression::Cast {
  1454. loc: *loc,
  1455. ty: ty.clone(),
  1456. expr: Box::new(filter(expr, ctx)),
  1457. },
  1458. Expression::BytesCast {
  1459. loc,
  1460. ty,
  1461. from,
  1462. expr,
  1463. } => Expression::BytesCast {
  1464. loc: *loc,
  1465. ty: ty.clone(),
  1466. from: from.clone(),
  1467. expr: Box::new(filter(expr, ctx)),
  1468. },
  1469. Expression::More {
  1470. loc,
  1471. signed,
  1472. left,
  1473. right,
  1474. } => Expression::More {
  1475. loc: *loc,
  1476. signed: *signed,
  1477. left: Box::new(filter(left, ctx)),
  1478. right: Box::new(filter(right, ctx)),
  1479. },
  1480. Expression::Less {
  1481. loc,
  1482. signed,
  1483. left,
  1484. right,
  1485. } => Expression::Less {
  1486. loc: *loc,
  1487. signed: *signed,
  1488. left: Box::new(filter(left, ctx)),
  1489. right: Box::new(filter(right, ctx)),
  1490. },
  1491. Expression::MoreEqual {
  1492. loc,
  1493. signed,
  1494. left,
  1495. right,
  1496. } => Expression::MoreEqual {
  1497. loc: *loc,
  1498. signed: *signed,
  1499. left: Box::new(filter(left, ctx)),
  1500. right: Box::new(filter(right, ctx)),
  1501. },
  1502. Expression::LessEqual {
  1503. loc,
  1504. signed,
  1505. left,
  1506. right,
  1507. } => Expression::LessEqual {
  1508. loc: *loc,
  1509. signed: *signed,
  1510. left: Box::new(filter(left, ctx)),
  1511. right: Box::new(filter(right, ctx)),
  1512. },
  1513. Expression::Equal { loc, left, right } => Expression::Equal {
  1514. loc: *loc,
  1515. left: Box::new(filter(left, ctx)),
  1516. right: Box::new(filter(right, ctx)),
  1517. },
  1518. Expression::NotEqual { loc, left, right } => Expression::NotEqual {
  1519. loc: *loc,
  1520. left: Box::new(filter(left, ctx)),
  1521. right: Box::new(filter(right, ctx)),
  1522. },
  1523. Expression::AdvancePointer {
  1524. pointer,
  1525. bytes_offset: offset,
  1526. } => Expression::AdvancePointer {
  1527. pointer: Box::new(filter(pointer, ctx)),
  1528. bytes_offset: Box::new(filter(offset, ctx)),
  1529. },
  1530. Expression::Not { loc, expr } => Expression::Not {
  1531. loc: *loc,
  1532. expr: Box::new(filter(expr, ctx)),
  1533. },
  1534. Expression::BitwiseNot { loc, ty, expr } => Expression::BitwiseNot {
  1535. loc: *loc,
  1536. ty: ty.clone(),
  1537. expr: Box::new(filter(expr, ctx)),
  1538. },
  1539. Expression::Negate {
  1540. loc,
  1541. ty,
  1542. overflowing,
  1543. expr,
  1544. } => Expression::Negate {
  1545. loc: *loc,
  1546. ty: ty.clone(),
  1547. overflowing: *overflowing,
  1548. expr: Box::new(filter(expr, ctx)),
  1549. },
  1550. Expression::Subscript {
  1551. loc,
  1552. ty: elem_ty,
  1553. array_ty,
  1554. expr,
  1555. index,
  1556. } => Expression::Subscript {
  1557. loc: *loc,
  1558. ty: elem_ty.clone(),
  1559. array_ty: array_ty.clone(),
  1560. expr: Box::new(filter(expr, ctx)),
  1561. index: Box::new(filter(index, ctx)),
  1562. },
  1563. Expression::StructMember {
  1564. loc,
  1565. ty,
  1566. expr,
  1567. member,
  1568. } => Expression::StructMember {
  1569. loc: *loc,
  1570. ty: ty.clone(),
  1571. expr: Box::new(filter(expr, ctx)),
  1572. member: *member,
  1573. },
  1574. Expression::AllocDynamicBytes {
  1575. loc,
  1576. ty,
  1577. size,
  1578. initializer,
  1579. } => Expression::AllocDynamicBytes {
  1580. loc: *loc,
  1581. ty: ty.clone(),
  1582. size: Box::new(filter(size, ctx)),
  1583. initializer: initializer.clone(),
  1584. },
  1585. Expression::StorageArrayLength {
  1586. loc,
  1587. ty,
  1588. array,
  1589. elem_ty,
  1590. } => Expression::StorageArrayLength {
  1591. loc: *loc,
  1592. ty: ty.clone(),
  1593. array: Box::new(filter(array, ctx)),
  1594. elem_ty: elem_ty.clone(),
  1595. },
  1596. Expression::StringCompare { loc, left, right } => Expression::StringCompare {
  1597. loc: *loc,
  1598. left: match left {
  1599. StringLocation::CompileTime(_) => left.clone(),
  1600. StringLocation::RunTime(expr) => {
  1601. StringLocation::RunTime(Box::new(filter(expr, ctx)))
  1602. }
  1603. },
  1604. right: match right {
  1605. StringLocation::CompileTime(_) => right.clone(),
  1606. StringLocation::RunTime(expr) => {
  1607. StringLocation::RunTime(Box::new(filter(expr, ctx)))
  1608. }
  1609. },
  1610. },
  1611. Expression::FormatString { loc, args } => {
  1612. let args = args.iter().map(|(f, e)| (*f, filter(e, ctx))).collect();
  1613. Expression::FormatString { loc: *loc, args }
  1614. }
  1615. Expression::Builtin {
  1616. loc,
  1617. tys,
  1618. kind: builtin,
  1619. args,
  1620. } => {
  1621. let args = args.iter().map(|e| filter(e, ctx)).collect();
  1622. Expression::Builtin {
  1623. loc: *loc,
  1624. tys: tys.clone(),
  1625. kind: *builtin,
  1626. args,
  1627. }
  1628. }
  1629. _ => self.clone(),
  1630. },
  1631. ctx,
  1632. )
  1633. }
  1634. fn external_function_selector(&self) -> Expression {
  1635. debug_assert!(
  1636. matches!(self.ty().deref_any(), Type::ExternalFunction { .. }),
  1637. "This is not an external function"
  1638. );
  1639. let loc = self.loc();
  1640. let struct_member = Expression::StructMember {
  1641. loc,
  1642. ty: Type::Ref(Box::new(Type::FunctionSelector)),
  1643. expr: Box::new(self.clone()),
  1644. member: 0,
  1645. };
  1646. Expression::Load {
  1647. loc,
  1648. ty: Type::FunctionSelector,
  1649. expr: Box::new(struct_member),
  1650. }
  1651. }
  1652. fn external_function_address(&self) -> Expression {
  1653. debug_assert!(
  1654. matches!(self.ty(), Type::ExternalFunction { .. }),
  1655. "This is not an external function"
  1656. );
  1657. let loc = self.loc();
  1658. let struct_member = Expression::StructMember {
  1659. loc,
  1660. ty: Type::Ref(Box::new(Type::Address(false))),
  1661. expr: Box::new(self.clone()),
  1662. member: 1,
  1663. };
  1664. Expression::Load {
  1665. loc,
  1666. ty: Type::Address(false),
  1667. expr: Box::new(struct_member),
  1668. }
  1669. }
  1670. }
  1671. #[derive(PartialEq, Eq, Debug, Clone, Copy)]
  1672. pub enum Builtin {
  1673. Accounts,
  1674. AddMod,
  1675. ArrayLength,
  1676. Balance,
  1677. Blake2_128,
  1678. Blake2_256,
  1679. BlockCoinbase,
  1680. BlockDifficulty,
  1681. BlockHash,
  1682. BlockNumber,
  1683. Calldata,
  1684. ChainId,
  1685. ContractCode,
  1686. Gasleft,
  1687. GasLimit,
  1688. Gasprice,
  1689. BaseFee,
  1690. PrevRandao,
  1691. /// GetAddress returns a pointer to the address. On Polkadot, this pointer points to the
  1692. /// scratch buffer, to which many syscall write. We strongly recommend loading the pointer
  1693. /// before using on Polkadot. This is not the case for Solana, though.
  1694. GetAddress,
  1695. ExtCodeSize,
  1696. MinimumBalance,
  1697. MulMod,
  1698. Keccak256,
  1699. Origin,
  1700. ReadFromBuffer,
  1701. Ripemd160,
  1702. Sender,
  1703. Slot,
  1704. Sha256,
  1705. Signature,
  1706. SignatureVerify,
  1707. Timestamp,
  1708. Value,
  1709. WriteAddress,
  1710. WriteInt8,
  1711. WriteInt16LE,
  1712. WriteInt32LE,
  1713. WriteInt64LE,
  1714. WriteInt128LE,
  1715. WriteInt256LE,
  1716. WriteUint16LE,
  1717. WriteUint32LE,
  1718. WriteUint64LE,
  1719. WriteUint128LE,
  1720. WriteUint256LE,
  1721. WriteBytes,
  1722. Concat,
  1723. RequireAuth,
  1724. AuthAsCurrContract,
  1725. ExtendTtl,
  1726. ExtendInstanceTtl,
  1727. AccessMapping,
  1728. }
  1729. impl From<&ast::Builtin> for Builtin {
  1730. fn from(ast_builtin: &ast::Builtin) -> Self {
  1731. match ast_builtin {
  1732. ast::Builtin::Accounts => Builtin::Accounts,
  1733. ast::Builtin::AddMod => Builtin::AddMod,
  1734. ast::Builtin::ArrayLength => Builtin::ArrayLength,
  1735. ast::Builtin::Balance => Builtin::Balance,
  1736. ast::Builtin::Blake2_128 => Builtin::Blake2_128,
  1737. ast::Builtin::Blake2_256 => Builtin::Blake2_256,
  1738. ast::Builtin::BlockCoinbase => Builtin::BlockCoinbase,
  1739. ast::Builtin::BlockDifficulty => Builtin::BlockDifficulty,
  1740. ast::Builtin::BlockHash => Builtin::BlockHash,
  1741. ast::Builtin::BlockNumber => Builtin::BlockNumber,
  1742. ast::Builtin::Calldata => Builtin::Calldata,
  1743. ast::Builtin::Gasleft => Builtin::Gasleft,
  1744. ast::Builtin::GasLimit => Builtin::GasLimit,
  1745. ast::Builtin::Gasprice => Builtin::Gasprice,
  1746. ast::Builtin::GetAddress => Builtin::GetAddress,
  1747. ast::Builtin::MinimumBalance => Builtin::MinimumBalance,
  1748. ast::Builtin::MulMod => Builtin::MulMod,
  1749. ast::Builtin::Keccak256 => Builtin::Keccak256,
  1750. ast::Builtin::Origin => Builtin::Origin,
  1751. ast::Builtin::ReadAddress
  1752. | ast::Builtin::ReadInt8
  1753. | ast::Builtin::ReadInt16LE
  1754. | ast::Builtin::ReadInt32LE
  1755. | ast::Builtin::ReadInt64LE
  1756. | ast::Builtin::ReadInt128LE
  1757. | ast::Builtin::ReadInt256LE
  1758. | ast::Builtin::ReadUint16LE
  1759. | ast::Builtin::ReadUint32LE
  1760. | ast::Builtin::ReadUint64LE
  1761. | ast::Builtin::ReadUint128LE
  1762. | ast::Builtin::ReadUint256LE => Builtin::ReadFromBuffer,
  1763. ast::Builtin::Ripemd160 => Builtin::Ripemd160,
  1764. ast::Builtin::Sender => Builtin::Sender,
  1765. ast::Builtin::Slot => Builtin::Slot,
  1766. ast::Builtin::Sha256 => Builtin::Sha256,
  1767. ast::Builtin::Signature => Builtin::Signature,
  1768. ast::Builtin::SignatureVerify => Builtin::SignatureVerify,
  1769. ast::Builtin::Timestamp => Builtin::Timestamp,
  1770. ast::Builtin::Value => Builtin::Value,
  1771. ast::Builtin::WriteAddress => Builtin::WriteAddress,
  1772. ast::Builtin::WriteInt8 => Builtin::WriteInt8,
  1773. ast::Builtin::WriteInt16LE => Builtin::WriteInt16LE,
  1774. ast::Builtin::WriteInt32LE => Builtin::WriteInt32LE,
  1775. ast::Builtin::WriteInt64LE => Builtin::WriteInt64LE,
  1776. ast::Builtin::WriteInt128LE => Builtin::WriteInt128LE,
  1777. ast::Builtin::WriteInt256LE => Builtin::WriteInt256LE,
  1778. ast::Builtin::WriteUint16LE => Builtin::WriteUint16LE,
  1779. ast::Builtin::WriteUint32LE => Builtin::WriteUint32LE,
  1780. ast::Builtin::WriteUint64LE => Builtin::WriteUint64LE,
  1781. ast::Builtin::WriteUint128LE => Builtin::WriteUint128LE,
  1782. ast::Builtin::WriteUint256LE => Builtin::WriteUint256LE,
  1783. ast::Builtin::WriteBytes | ast::Builtin::WriteString => Builtin::WriteBytes,
  1784. ast::Builtin::ChainId => Builtin::ChainId,
  1785. ast::Builtin::BaseFee => Builtin::BaseFee,
  1786. ast::Builtin::PrevRandao => Builtin::PrevRandao,
  1787. ast::Builtin::ContractCode => Builtin::ContractCode,
  1788. ast::Builtin::StringConcat | ast::Builtin::BytesConcat => Builtin::Concat,
  1789. ast::Builtin::RequireAuth => Builtin::RequireAuth,
  1790. ast::Builtin::AuthAsCurrContract => Builtin::AuthAsCurrContract,
  1791. ast::Builtin::ExtendTtl => Builtin::ExtendTtl,
  1792. ast::Builtin::ExtendInstanceTtl => Builtin::ExtendInstanceTtl,
  1793. _ => panic!("Builtin should not be in the cfg"),
  1794. }
  1795. }
  1796. }