Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions libsolidity/codegen/mlir/SolidityToMLIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ void SolidityToMLIRPass::genDeleteExpr(mlir::Value addr, mlir::Location loc) {
mlir::Type pointeeTy =
mlir::cast<mlir::sol::PointerType>(addrTy).getPointeeType();

if (mlir::sol::isRefType(pointeeTy)) {
if (!mlir::sol::isScalar(pointeeTy)) {
genAssign(addr, genZeroedVal(toMemoryType(pointeeTy), loc), loc);
return;
}
Expand Down Expand Up @@ -1899,13 +1899,11 @@ SolidityToMLIRPass::genExprs(FunctionCall const &call) {
const auto &event =
dynamic_cast<EventDefinition const &>(calleeTy->declaration());

// Lower and track the indexed and non-indexed args.
// Lower and track the indexed and non-indexed args. The indexed-arg
// topic computation (cleanup for value types, keccak256-of-packed-encode
// for reference types) is handled by EmitOpLowering.
std::vector<mlir::Value> indexedArgs, nonIndexedArgs;
for (size_t i = 0; i < event.parameters().size(); ++i) {
assert(dynamic_cast<IntegerType const *>(calleeTy->parameterTypes()[i]) ||
dynamic_cast<AddressType const *>(calleeTy->parameterTypes()[i]) ||
dynamic_cast<ContractType const *>(calleeTy->parameterTypes()[i]));

// TODO? YulUtilFunctions::conversionFunction
mlir::Value arg =
genRValExpr(*astArgs[i], getType(calleeTy->parameterTypes()[i]));
Expand Down Expand Up @@ -1990,8 +1988,7 @@ SolidityToMLIRPass::genExprs(FunctionCall const &call) {
}
} else {
b.create<mlir::sol::RequireOp>(loc, genRValExpr(*astArgs[0]),
mlir::StringAttr{},
mlir::ValueRange{});
mlir::StringAttr{}, mlir::ValueRange{});
}
return {};
}
Expand Down Expand Up @@ -2185,8 +2182,11 @@ SolidityToMLIRPass::genExprs(FunctionCall const &call) {
// Handle:
// str.push(0x41);
//
// Cast the argument to the parameter type (bytes1) so that string
// literals like "f" are folded to a single byte before the op is built.
b.create<mlir::sol::PushStringOp>(
loc, genRValExpr(memberAcc->expression()), genRValExpr(*astArgs[0]));
loc, genRValExpr(memberAcc->expression()),
genRValExpr(*astArgs[0], getType(calleeTy->parameterTypes()[0])));
return resVals;
}

Expand Down Expand Up @@ -2283,8 +2283,10 @@ SolidityToMLIRPass::genExprs(TupleExpression const &tuple) {

void SolidityToMLIRPass::genAssign(mlir::Value lhs, mlir::Value rhs,
mlir::Location loc) {
// Generate copy for assignment to storage reference types.
if (mlir::sol::isNonPtrRefType(rhs.getType()) &&
// Aggregate copy into storage. Pointer LHS falls through so genCast can fold
// a literal RHS to the element type (e.g. bytes.push() = "G").
if (mlir::sol::isNonPtrRefType(lhs.getType()) &&
mlir::sol::isNonPtrRefType(rhs.getType()) &&
mlir::sol::getDataLocation(lhs.getType()) ==
mlir::sol::DataLocation::Storage) {
b.create<mlir::sol::CopyOp>(loc, rhs, lhs);
Expand Down
28 changes: 28 additions & 0 deletions test/libsolidity/semanticTests/mlir/abi.sol
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,32 @@ contract C {
bytes memory b = abi.encodeWithSelector(I.foo.selector, x);
return keccak256(a) == keccak256(b);
}

// abi.encode vs abi.encodePacked over the same args: length, hash
// difference, and equality of repeated invocations.
function enc_vs_packed_same_args() public pure returns (bool, bool, bool, bool) {
uint8[] memory xs = new uint8[](3);
xs[0] = 1;
xs[1] = 2;
xs[2] = 3;
bytes memory tuple = abi.encode("abc", xs, bytes3(0xaabbcc));
bytes memory packed = abi.encodePacked("abc", xs, bytes3(0xaabbcc));
return (
tuple.length > packed.length,
keccak256(tuple) != keccak256(packed),
keccak256(abi.encode("abc", xs, bytes3(0xaabbcc))) == keccak256(tuple),
keccak256(abi.encodePacked("abc", xs, bytes3(0xaabbcc))) == keccak256(packed)
);
}

// keccak256(abi.encode(...)) vs keccak256(abi.encodePacked(...)) - pins
// the exact hashes plus the inequality.
function keccak_enc_vs_packed() public pure returns (bytes32, bytes32, bool) {
uint16[2] memory a = [uint16(0x1234), uint16(0xabcd)];
bytes32 tupleHash = keccak256(abi.encode("payload", a, uint8(7)));
bytes32 packedHash = keccak256(abi.encodePacked("payload", a, uint8(7)));
return (tupleHash, packedHash, tupleHash != packedHash);
}
}

// ====
Expand Down Expand Up @@ -436,3 +462,5 @@ contract C {
// ec_tuple(uint256,uint8): 1, 2 -> 0x20, 0x44, left(0x06450a21), left(0x00000001), left(0x00000002)
// ec_decl(uint256): 1 -> 0x20, 0x24, left(0x2fbebd38), left(0x00000001)
// ec_ews(uint256): 1 -> 1
// enc_vs_packed_same_args() -> true, true, true, true
// keccak_enc_vs_packed() -> 0xc5281913de15038cf4b5d64cf1a05399d329c271980c67e3b7c5d456fd21e4b1, 0x39141b1e392d397bb25c932cad00ea54a6f71a14b1e0e88eac0502c9362c9b16, true
59 changes: 59 additions & 0 deletions test/libsolidity/semanticTests/mlir/bytes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,56 @@ contract C {
str.pop();
return str;
}

// push(arg) - argument forms convertible to bytes1.
function push_str_lit(bytes memory a) public returns (bytes memory) {
str = a;
str.push("B");
return str;
}
function push_hex_lit(bytes memory a) public returns (bytes memory) {
str = a;
str.push(hex"43");
return str;
}
function push_cast(bytes memory a) public returns (bytes memory) {
str = a;
str.push(bytes1(0x44));
return str;
}
function push_cast_from_uint8(bytes memory a) public returns (bytes memory) {
str = a;
str.push(bytes1(uint8(0x45)));
return str;
}
function push_index(bytes memory a) public returns (bytes memory) {
str = a;
str2 = "Z";
str.push(str2[0]);
return str;
}

// push() = arg - reference-assignment forms convertible to bytes1.
function push_ref_str_lit(bytes memory a) public returns (bytes memory) {
str = a;
str.push() = "G";
return str;
}
function push_ref_hex_lit(bytes memory a) public returns (bytes memory) {
str = a;
str.push() = hex"48";
return str;
}
function push_ref_cast(bytes memory a) public returns (bytes memory) {
str = a;
str.push() = bytes1(0x49);
return str;
}
function push_ref_void(bytes memory a) public returns (uint) {
str = a;
str.push();
return str.length;
}
}

// ====
Expand Down Expand Up @@ -200,3 +250,12 @@ contract C {
// idx_write(bytes,uint256, bytes1): 96, 31, "Z", 33, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX", "Y" -> 0x20, 33, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaZ", "Y"
// idx_write(bytes,uint256, bytes1): 96, 32, "Z", 33, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX", "Y" -> 0x20, 33, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX", "Z"
// idx_write(bytes,uint256, bytes1): 96, 5, "X", 5, "hello" -> FAILURE, hex"4e487b71", 0x32
// push_str_lit(bytes): 32, 2, "ab" -> 0x20, 3, "abB"
// push_hex_lit(bytes): 32, 2, "ab" -> 0x20, 3, "abC"
// push_cast(bytes): 32, 2, "ab" -> 0x20, 3, "abD"
// push_cast_from_uint8(bytes): 32, 2, "ab" -> 0x20, 3, "abE"
// push_index(bytes): 32, 2, "ab" -> 0x20, 3, "abZ"
// push_ref_str_lit(bytes): 32, 2, "ab" -> 0x20, 3, "abG"
// push_ref_hex_lit(bytes): 32, 2, "ab" -> 0x20, 3, "abH"
// push_ref_cast(bytes): 32, 2, "ab" -> 0x20, 3, "abI"
// push_ref_void(bytes): 32, 2, "ab" -> 3
97 changes: 97 additions & 0 deletions test/libsolidity/semanticTests/mlir/event_arg_types_all.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
contract C {
enum En { A, B, C }
type Udvt is uint64;
struct S { uint x; bool y; bytes32 z; }

// Indexed: value types
event Ibool(bool indexed);
event Iint(int8 indexed, uint256 indexed);
event Iaddr(address indexed);
event Ibytes(bytes1 indexed, bytes32 indexed);
event Ienum(En indexed);
event Iudvt(Udvt indexed);
event Icontract(C indexed);
event Ifnptr(function() external indexed);

// Indexed: reference types
event Istr(string indexed);
event Ibts(bytes indexed);
event Idynarr(uint[] indexed);
event Ifixarr(uint[3] indexed);

// Non-indexed: full ABI tuple
event N(
bool, int256, uint256, address,
bytes1, bytes32, En, Udvt,
string, bytes, uint[], uint[3], S
);

// Anonymous (4 indexed)
event Anon(uint indexed, uint indexed, uint indexed, uint indexed) anonymous;

// Mixed indexed + non-indexed
event Mixed(uint indexed, string s, uint[] arr);

function f() public {
emit Ibool(true);
emit Iint(-1, 0xff);
emit Iaddr(address(0xabc));
emit Ibytes(0x01, 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00);
emit Ienum(En.B);
emit Iudvt(Udvt.wrap(0xcafe));
emit Icontract(this);
emit Ifnptr(this.f);

emit Istr("hello");
emit Ibts(hex"deadbeef");

uint[] memory a = new uint[](3);
a[0] = 1; a[1] = 2; a[2] = 3;
emit Idynarr(a);

uint[3] memory b = [uint(10), 20, 30];
emit Ifixarr(b);

emit N(
true, -1, 0xff, address(0x123),
0x42, 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00, En.C, Udvt.wrap(0xfeed),
"data", hex"01020304", a, b, S(100, true, 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00)
);

emit Anon(0x11, 0x22, 0x33, 0x44);
emit Mixed(7, "key", a);

// Keccak edge cases: empty / multi-word reference args.
emit Istr("");
emit Ibts(hex"");
uint[] memory empty = new uint[](0);
emit Idynarr(empty);
emit Istr("ABCDEFGHIJKLMNOPQRSTUVWXYZ-this-string-is-longer-than-32-bytes");
emit Ibts(hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00");
}
}

// ====
// compileViaMlir: true
// ----
// f() ->
// ~ emit Ibool(bool): #0x01
// ~ emit Iint(int8,uint256): #0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, #0xff
// ~ emit Iaddr(address): #0x0abc
// ~ emit Ibytes(bytes1,bytes32): #0x0100000000000000000000000000000000000000000000000000000000000000, #0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00
// ~ emit Ienum(uint8): #0x01
// ~ emit Iudvt(uint64): #0xcafe
// ~ emit Icontract(address): #0xc06afe3a8444fc0004668591e8306bfb9968e79e
// ~ emit Ifnptr(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79e26121ff00000000000000000
// ~ emit Istr(string): #0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8
// ~ emit Ibts(bytes): #0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1
// ~ emit Idynarr(uint256[]): #0x6e0c627900b24bd432fe7b1f713f1b0744091a646a9fe4a65a18dfed21f2949c
// ~ emit Ifixarr(uint256[3]): #0x993a17e836e3d65fac6232390ad969f667a21cb52cf3dc1bcd207d28a216c944
// ~ emit N(bool,int256,uint256,address,bytes1,bytes32,uint8,uint64,string,bytes,uint256[],uint256[3],(uint256,bool,bytes32)): true, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0xff, 0x0123, "B", 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00, 0x02, 0xfeed, 0x0220, 0x0260, 0x02a0, 0x0a, 0x14, 0x1e, 0x64, 0x01, 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00, 0x04, "data", 0x04, 0x0102030400000000000000000000000000000000000000000000000000000000, 0x03, 0x01, 0x02, 0x03
// ~ emit <anonymous>: #0x11, #0x22, #0x33, #0x44
// ~ emit Mixed(uint256,string,uint256[]): #0x07, 0x40, 0x80, 0x03, "key", 0x03, 0x01, 0x02, 0x03
// ~ emit Istr(string): #0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
// ~ emit Ibts(bytes): #0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
// ~ emit Idynarr(uint256[]): #0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
// ~ emit Istr(string): #0xd40a805ab6f9f68c502048cc3806684dab75031166a4c09a259df77aad1c1121
// ~ emit Ibts(bytes): #0xeaacc4b644af7f3e1b9345c8a687198b505eeeafa66dc79201a9b856e7a29125
Loading