Skip to content

Commit 7dc3397

Browse files
[mlir] Add lowering for abi.encodeWithSelector
Signed-off-by: Vladimir Radosavljevic <vr@matterlabs.dev>
1 parent 56b9daa commit 7dc3397

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

mlir/include/mlir/Dialect/Sol/SolOps.td

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,12 +346,25 @@ def Sol_SliceOp : Sol_Op<"slice"> {
346346
}];
347347
}
348348

349-
def Sol_EncodeOp : Sol_Op<"encode"> {
349+
def Sol_Bytes4SelectorType : Type<
350+
CPred<"::llvm::isa<::mlir::sol::BytesType>($_self) && "
351+
"::llvm::cast<::mlir::sol::BytesType>($_self).getSize() == 4">,
352+
"!sol.bytes<4>">;
353+
354+
def Sol_EncodeOp : Sol_Op<"encode", [AttrSizedOperandSegments]> {
350355
// When $packed is set, values are encoded without per-element padding.
351-
let arguments = (ins Variadic<AnyType>:$ins, UnitAttr:$packed);
356+
// When $selector is set, it is prepended as the first 4 bytes while $ins are
357+
// ABI-encoded as a tuple.
358+
let arguments = (ins Variadic<AnyType>:$ins,
359+
Optional<Sol_Bytes4SelectorType>:$selector,
360+
UnitAttr:$packed);
352361
// FIXME: AnyType -> Sol_StringType causes the asm printer to miss the prefix!
353362
let results = (outs AnyType:$res);
354-
let assemblyFormat = "($ins^ `:` type($ins))? `:` type($res) attr-dict";
363+
let assemblyFormat = [{
364+
(`selector` `(` $selector^ `)`)? ($ins^)?
365+
`:` type($selector) type($ins)
366+
`:` type($res) attr-dict
367+
}];
355368
}
356369

357370
def Sol_DecodeOp : Sol_Op<"decode"> {

mlir/lib/Conversion/SolToStandard/SolToYul.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,17 +2086,32 @@ struct EncodeOpLowering : public OpConversionPattern<sol::EncodeOp> {
20862086
if (op.getPacked()) {
20872087
Value dataStart =
20882088
r.create<arith::AddIOp>(loc, freePtr, bExt.genI256Const(32));
2089-
Value dataEnd = evmB.genABIPackedEncoding(
2090-
op.getOperandTypes(), adaptor.getOperands(), dataStart);
2089+
Value dataEnd = evmB.genABIPackedEncoding(op.getIns().getType(),
2090+
adaptor.getIns(), dataStart);
20912091
Value dataSize = r.create<arith::SubIOp>(loc, dataEnd, dataStart);
20922092
r.create<yul::MStoreOp>(loc, freePtr, dataSize);
20932093
Value allocationSize = r.create<arith::SubIOp>(loc, dataEnd, freePtr);
20942094
evmB.genFreePtrUpd(freePtr, allocationSize);
2095+
} else if (op.getSelector()) {
2096+
assert(adaptor.getSelector() && "selector operand is required");
2097+
2098+
Value selectorAddr =
2099+
r.create<arith::AddIOp>(loc, freePtr, bExt.genI256Const(32));
2100+
r.create<yul::MStoreOp>(loc, selectorAddr, adaptor.getSelector());
2101+
2102+
Value tupleStart =
2103+
r.create<arith::AddIOp>(loc, selectorAddr, bExt.genI256Const(4));
2104+
Value tupleEnd = evmB.genABITupleEncoding(op.getIns().getType(),
2105+
adaptor.getIns(), tupleStart);
2106+
Value dataSize = r.create<arith::SubIOp>(loc, tupleEnd, selectorAddr);
2107+
r.create<yul::MStoreOp>(loc, freePtr, dataSize);
2108+
Value allocationSize = r.create<arith::SubIOp>(loc, tupleEnd, freePtr);
2109+
evmB.genFreePtrUpd(freePtr, allocationSize);
20952110
} else {
20962111
Value tupleStart =
20972112
r.create<arith::AddIOp>(loc, freePtr, bExt.genI256Const(32));
2098-
Value tupleEnd = evmB.genABITupleEncoding(
2099-
op.getOperandTypes(), adaptor.getOperands(), tupleStart);
2113+
Value tupleEnd = evmB.genABITupleEncoding(op.getIns().getType(),
2114+
adaptor.getIns(), tupleStart);
21002115
Value tupleSize = r.create<arith::SubIOp>(loc, tupleEnd, tupleStart);
21012116
r.create<yul::MStoreOp>(loc, freePtr, tupleSize);
21022117
Value allocationSize = r.create<arith::SubIOp>(loc, tupleEnd, freePtr);

0 commit comments

Comments
 (0)