| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- // SPDX-License-Identifier: Apache-2.0
- use crate::lir_tests::helpers::{identifier, new_printer, new_vartable, num_literal, set_tmp};
- use crate::{num_literal, stringfy_insn};
- use num_bigint::BigInt;
- use solang::codegen::cfg;
- use solang::lir::expressions::{BinaryOperator, Expression};
- use solang::lir::instructions::Instruction;
- use solang::lir::lir_type::{InternalCallTy, PhiInput, StructType, Type};
- use solang::sema::ast::{ArrayLength, CallTy};
- use solang_parser::pt::Loc;
- #[test]
- fn test_stringfy_nop_insn() {
- assert_eq!(
- stringfy_insn!(&new_printer(&new_vartable()), &Instruction::Nop),
- "nop;"
- );
- }
- // ReturnData
- #[test]
- fn test_stringfy_returndata_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 0, Type::Bytes(1));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::ReturnData {
- loc: /*missing from cfg*/ Loc::Codegen,
- data: identifier(0),
- data_len: num_literal!(1),
- }
- ),
- "return_data bytes1(%temp.ssa_ir.0) of length uint8(1);"
- );
- }
- // ReturnCode
- #[test]
- fn test_stringfy_returncode_insn() {
- assert_eq!(
- stringfy_insn!(
- &new_printer(&new_vartable()),
- &Instruction::ReturnCode {
- loc: /*missing from cfg*/ Loc::Codegen,
- code: cfg::ReturnCode::AbiEncodingInvalid,
- }
- ),
- "return_code \"abi encoding invalid\";"
- );
- assert_eq!(
- stringfy_insn!(
- &new_printer(&new_vartable()),
- &Instruction::ReturnCode {
- loc: /*missing from cfg*/ Loc::Codegen,
- code: cfg::ReturnCode::AccountDataTooSmall,
- }
- ),
- "return_code \"account data too small\";"
- );
- }
- // Set
- #[test]
- fn test_stringfy_set_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 121, Type::Uint(8));
- set_tmp(&mut v, 122, Type::Uint(8));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Set {
- loc: Loc::Codegen,
- res: 122,
- expr: Expression::BinaryExpr {
- loc: Loc::Codegen,
- operator: BinaryOperator::Mul { overflowing: true },
- left: Box::new(num_literal!(1)),
- right: Box::new(identifier(121))
- }
- }
- ),
- "uint8 %temp.ssa_ir.122 = uint8(1) (of)* uint8(%temp.ssa_ir.121);"
- );
- }
- // Store
- #[test]
- fn test_stringfy_store_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 0, Type::Ptr(Box::new(Type::Uint(8))));
- set_tmp(&mut v, 1, Type::Uint(8));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Store {
- loc: /*missing from cfg*/ Loc::Codegen,
- dest: identifier(0),
- data: identifier(1),
- }
- ),
- "store uint8(%temp.ssa_ir.1) to ptr<uint8>(%temp.ssa_ir.0);"
- );
- // store a number
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Store {
- loc: /*missing from cfg*/ Loc::Codegen,
- dest: identifier(0),
- data: num_literal!(1),
- }
- ),
- "store uint8(1) to ptr<uint8>(%temp.ssa_ir.0);"
- );
- }
- // PushMemory
- #[test]
- fn test_stringfy_push_memory_insn() {
- let mut v = new_vartable();
- set_tmp(
- &mut v,
- 3,
- Type::Ptr(Box::new(Type::Array(
- Box::new(Type::Uint(32)),
- vec![ArrayLength::Fixed(BigInt::from(3))],
- ))),
- );
- set_tmp(&mut v, 101, Type::Uint(32));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::PushMemory {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: 101,
- array: 3,
- value: num_literal!(1, 32),
- }
- ),
- "uint32 %temp.ssa_ir.101 = push_mem ptr<uint32[3]>(%temp.ssa_ir.3) uint32(1);"
- );
- }
- #[test]
- fn test_stringfy_pop_memory_insn() {
- let mut v = new_vartable();
- set_tmp(
- &mut v,
- 3,
- Type::Ptr(Box::new(Type::Array(
- Box::new(Type::Uint(32)),
- vec![ArrayLength::Fixed(BigInt::from(3))],
- ))),
- );
- set_tmp(&mut v, 101, Type::Uint(32));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::PopMemory {
- res: 101,
- array: 3,
- loc: Loc::Codegen,
- }
- ),
- "uint32 %temp.ssa_ir.101 = pop_mem ptr<uint32[3]>(%temp.ssa_ir.3);"
- );
- }
- // LoadStorage
- #[test]
- fn test_stringfy_load_storage_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 101, Type::Uint(32));
- set_tmp(&mut v, 3, Type::StoragePtr(false, Box::new(Type::Uint(32))));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::LoadStorage {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: 101,
- storage: identifier(3)
- }
- ),
- "uint32 %temp.ssa_ir.101 = load_storage storage_ptr<uint32>(%temp.ssa_ir.3);"
- );
- }
- #[test]
- fn test_stringfy_clear_storage_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 3, Type::StoragePtr(false, Box::new(Type::Uint(32))));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::ClearStorage {
- loc: /*missing from cfg*/ Loc::Codegen,
- storage: identifier(3)
- }
- ),
- "clear_storage storage_ptr<uint32>(%temp.ssa_ir.3);"
- );
- }
- #[test]
- fn test_stringfy_set_storage_insn() {
- let mut v = new_vartable();
- set_tmp(
- &mut v,
- 1,
- Type::StoragePtr(false, Box::new(Type::Uint(256))),
- );
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::SetStorage {
- loc: /*missing from cfg*/ Loc::Codegen,
- value: num_literal(13445566, false, 256),
- storage: identifier(1)
- }
- ),
- "set_storage storage_ptr<uint256>(%temp.ssa_ir.1) uint256(13445566);"
- );
- }
- #[test]
- fn test_stringfy_set_storage_bytes_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 1, Type::Bytes(32));
- set_tmp(
- &mut v,
- 2,
- Type::StoragePtr(false, Box::new(Type::Bytes(32))),
- );
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::SetStorageBytes {
- loc: /*missing from cfg*/ Loc::Codegen,
- value: identifier(1),
- storage: identifier(2),
- offset: num_literal!(3)
- }
- ),
- "set_storage_bytes storage_ptr<bytes32>(%temp.ssa_ir.2) offset:uint8(3) value:bytes32(%temp.ssa_ir.1);"
- );
- }
- #[test]
- fn test_stringfy_push_storage_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 101, Type::Uint(32));
- set_tmp(
- &mut v,
- 3,
- Type::StoragePtr(
- false,
- Box::new(Type::Array(
- Box::new(Type::Uint(32)),
- vec![ArrayLength::Fixed(BigInt::from(3))],
- )),
- ),
- );
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::PushStorage {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: 101,
- value: Some(num_literal!(1, 32)),
- storage: identifier(3)
- }
- ),
- "uint32 %temp.ssa_ir.101 = push_storage storage_ptr<uint32[3]>(%temp.ssa_ir.3) uint32(1);"
- );
- }
- #[test]
- fn test_stringfy_pop_storage_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 123, Type::Uint(32));
- set_tmp(
- &mut v,
- 3,
- Type::StoragePtr(
- false,
- Box::new(Type::Array(
- Box::new(Type::Uint(32)),
- vec![ArrayLength::Fixed(BigInt::from(3))],
- )),
- ),
- );
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::PopStorage {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: Some(123),
- storage: identifier(3)
- }
- ),
- "uint32 %temp.ssa_ir.123 = pop_storage storage_ptr<uint32[3]>(%temp.ssa_ir.3);"
- );
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::PopStorage {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: None,
- storage: identifier(3)
- }
- ),
- "pop_storage storage_ptr<uint32[3]>(%temp.ssa_ir.3);"
- )
- }
- #[test]
- fn test_stringfy_call_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 1, Type::Uint(8));
- set_tmp(&mut v, 2, Type::Uint(64));
- set_tmp(&mut v, 3, Type::Uint(8));
- set_tmp(&mut v, 133, Type::Uint(64));
- set_tmp(
- &mut v,
- 123,
- Type::Ptr(Box::new(Type::Function {
- params: vec![Type::Uint(8), Type::Uint(64), Type::Uint(64)],
- returns: vec![Type::Uint(8), Type::Uint(64), Type::Uint(8)],
- })),
- );
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Call {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: vec![1, 2, 3],
- call: InternalCallTy::Builtin { ast_func_no: 123 },
- args: vec![num_literal!(3), identifier(133), num_literal!(6, 64)],
- }
- ),
- "uint8 %temp.ssa_ir.1, uint64 %temp.ssa_ir.2, uint8 %temp.ssa_ir.3 = call builtin#123(uint8(3), uint64(%temp.ssa_ir.133), uint64(6));"
- );
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Call {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: vec![1, 2, 3],
- call: InternalCallTy::Dynamic(identifier(123)),
- args: vec![num_literal!(3), identifier(133), num_literal!(6, 64)],
- }
- ),
- "uint8 %temp.ssa_ir.1, uint64 %temp.ssa_ir.2, uint8 %temp.ssa_ir.3 = call ptr<function (uint8, uint64, uint64) returns (uint8, uint64, uint8)>(%temp.ssa_ir.123)(uint8(3), uint64(%temp.ssa_ir.133), uint64(6));"
- );
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Call {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: vec![1, 2, 3],
- call: InternalCallTy::Static { cfg_no: 123 },
- args: vec![num_literal!(3), identifier(133), num_literal!(6, 64)],
- }
- ),
- "uint8 %temp.ssa_ir.1, uint64 %temp.ssa_ir.2, uint8 %temp.ssa_ir.3 = call function#123(uint8(3), uint64(%temp.ssa_ir.133), uint64(6));"
- );
- }
- // ExternalCall
- #[test]
- fn test_stringfy_external_call_insn() {
- let mut v = new_vartable();
- // success
- set_tmp(&mut v, 1, Type::Bool);
- // payload
- set_tmp(&mut v, 3, Type::Bytes(32));
- // value
- set_tmp(&mut v, 4, Type::Uint(64));
- // gas
- set_tmp(&mut v, 7, Type::Uint(64));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::ExternalCall {
- success: Some(1),
- address: None,
- payload: identifier(3),
- value: identifier(4),
- accounts: solang::sema::ast::ExternalCallAccounts::AbsentArgument,
- seeds: None,
- gas: identifier(7),
- callty: CallTy::Regular,
- contract_function_no: None,
- flags: None,
- loc: Loc::Codegen,
- }
- ),
- "bool %temp.ssa_ir.1 = call_ext [regular] address:_ payload:bytes32(%temp.ssa_ir.3) value:uint64(%temp.ssa_ir.4) gas:uint64(%temp.ssa_ir.7) accounts:absent seeds:_ contract_no:_, function_no:_ flags:_;"
- );
- }
- #[test]
- fn test_stringfy_print_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 3, Type::Uint(8));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Print {
- loc: /*missing from cfg*/ Loc::Codegen,
- operand: identifier(3)
- }
- ),
- "print uint8(%temp.ssa_ir.3);"
- );
- }
- #[test]
- fn test_stringfy_memcopy_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 3, Type::Bytes(32));
- set_tmp(&mut v, 4, Type::Bytes(16));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::MemCopy {
- loc: /*missing from cfg*/ Loc::Codegen,
- src: identifier(3),
- dest: identifier(4),
- bytes: num_literal!(16)
- }
- ),
- "memcopy bytes32(%temp.ssa_ir.3) to bytes16(%temp.ssa_ir.4) for uint8(16) bytes;"
- )
- }
- #[test]
- fn test_stringfy_value_transfer_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 1, Type::Bool);
- set_tmp(
- &mut v,
- 2,
- Type::Array(
- Box::new(Type::Uint(8)),
- vec![ArrayLength::Fixed(BigInt::from(32))],
- ),
- );
- set_tmp(&mut v, 3, Type::Uint(8));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::ValueTransfer {
- loc: /*missing from cfg*/ Loc::Codegen,
- success: Some(1),
- address: identifier(2),
- value: identifier(3),
- }
- ),
- "bool %temp.ssa_ir.1 = value_transfer uint8(%temp.ssa_ir.3) to uint8[32](%temp.ssa_ir.2);"
- );
- }
- #[test]
- fn test_stringfy_selfdestruct_insn() {
- let mut v = new_vartable();
- set_tmp(
- &mut v,
- 3,
- Type::Ptr(Box::new(Type::Struct(StructType::UserDefined(0)))),
- );
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::SelfDestruct {
- loc: /*missing from cfg*/ Loc::Codegen,
- recipient: identifier(3)
- }
- ),
- "self_destruct ptr<struct.0>(%temp.ssa_ir.3);"
- )
- }
- #[test]
- fn test_stringfy_emit_event_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 1, Type::Bytes(32));
- set_tmp(&mut v, 2, Type::Bytes(32));
- set_tmp(&mut v, 3, Type::Bytes(32));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::EmitEvent {
- loc: /*missing from cfg*/ Loc::Codegen,
- event_no: 13,
- topics: vec![identifier(1), identifier(2)],
- data: identifier(3)
- }
- ),
- "emit event#13 to topics[bytes32(%temp.ssa_ir.1), bytes32(%temp.ssa_ir.2)], data: bytes32(%temp.ssa_ir.3);"
- )
- }
- #[test]
- fn test_stringfy_branch_insn() {
- assert_eq!(
- stringfy_insn!(
- &new_printer(&new_vartable()),
- &Instruction::Branch {
- loc: /*missing from cfg*/ Loc::Codegen,
- block: 3
- }
- ),
- "br block#3;"
- )
- }
- #[test]
- fn test_stringfy_branch_cond_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 3, Type::Bool);
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::BranchCond {
- loc: /*missing from cfg*/ Loc::Codegen,
- cond: identifier(3),
- true_block: 5,
- false_block: 6
- }
- ),
- "cbr bool(%temp.ssa_ir.3) block#5 else block#6;"
- )
- }
- #[test]
- fn test_stringfy_switch_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 1, Type::Uint(8));
- set_tmp(&mut v, 4, Type::Uint(8));
- set_tmp(&mut v, 5, Type::Uint(8));
- set_tmp(&mut v, 6, Type::Uint(8));
- let printer = new_printer(&v);
- let s = stringfy_insn!(
- &printer,
- &Instruction::Switch {
- loc: /*missing from cfg*/ Loc::Codegen,
- cond: identifier(1),
- cases: vec![
- (identifier(4), 11),
- (identifier(5), 12),
- (identifier(6), 13),
- ],
- default: 14,
- }
- );
- assert_eq!(
- s,
- r#"switch uint8(%temp.ssa_ir.1):
- case: uint8(%temp.ssa_ir.4) => block#11,
- case: uint8(%temp.ssa_ir.5) => block#12,
- case: uint8(%temp.ssa_ir.6) => block#13
- default: block#14;"#
- )
- }
- #[test]
- fn test_stringfy_return_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 1, Type::Uint(8));
- set_tmp(&mut v, 2, Type::Bytes(32));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Return {
- loc: /*missing from cfg*/ Loc::Codegen,
- value: vec![identifier(1), identifier(2)]
- }
- ),
- "return uint8(%temp.ssa_ir.1), bytes32(%temp.ssa_ir.2);"
- )
- }
- #[test]
- fn test_stringfy_assert_failure_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 3, Type::Bytes(32));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::AssertFailure {
- loc: /*missing from cfg*/ Loc::Codegen,
- encoded_args: Some(identifier(3))
- }
- ),
- "assert_failure bytes32(%temp.ssa_ir.3);"
- );
- assert_eq!(
- stringfy_insn!(
- &new_printer(&new_vartable()),
- &Instruction::AssertFailure {
- loc: /*missing from cfg*/ Loc::Codegen,
- encoded_args: None
- }
- ),
- "assert_failure;"
- )
- }
- #[test]
- fn test_stringfy_phi_insn() {
- let mut v = new_vartable();
- set_tmp(&mut v, 1, Type::Uint(8));
- set_tmp(&mut v, 2, Type::Uint(8));
- set_tmp(&mut v, 12, Type::Uint(8));
- let printer = new_printer(&v);
- assert_eq!(
- stringfy_insn!(
- &printer,
- &Instruction::Phi {
- loc: /*missing from cfg*/ Loc::Codegen,
- res: 12,
- vars: vec![
- PhiInput::new(identifier(1), 13),
- PhiInput::new(identifier(2), 14)
- ],
- }
- ),
- "uint8 %temp.ssa_ir.12 = phi [uint8(%temp.ssa_ir.1), block#13], [uint8(%temp.ssa_ir.2), block#14];"
- )
- }
|