Skip to content

Commit 0648815

Browse files
committed
[mlir][evm] Lower signextend builtin
1 parent 3a61e40 commit 0648815

File tree

5 files changed

+91
-0
lines changed

5 files changed

+91
-0
lines changed

libsolidity/codegen/mlir/Target/EVM/YulToStandard.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,22 @@ struct MulModOpLowering : public OpRewritePattern<yul::MulModOp> {
106106
}
107107
};
108108

109+
struct SignExtendOpLowering : public OpRewritePattern<yul::SignExtendOp> {
110+
using OpRewritePattern<yul::SignExtendOp>::OpRewritePattern;
111+
112+
LogicalResult matchAndRewrite(yul::SignExtendOp op,
113+
PatternRewriter &r) const override {
114+
evm::Builder evmB(r, op.getLoc());
115+
116+
r.replaceOpWithNewOp<LLVM::IntrCallOp>(
117+
op, llvm::Intrinsic::evm_signextend,
118+
/*resTy=*/r.getIntegerType(256),
119+
/*ins=*/ValueRange{op.getVal(), op.getOff()}, "evm.signextend");
120+
121+
return success();
122+
}
123+
};
124+
109125
struct LogOpLowering : public OpRewritePattern<yul::LogOp> {
110126
using OpRewritePattern<yul::LogOp>::OpRewritePattern;
111127

@@ -776,6 +792,7 @@ void evm::populateYulPats(RewritePatternSet &pats) {
776792
UpdFreePtrOpLowering,
777793
Keccak256OpLowering,
778794
ExpOpLowering,
795+
SignExtendOpLowering,
779796
LogOpLowering,
780797
AddressOpLowering,
781798
CallerOpLowering,

libsolidity/codegen/mlir/Yul/YulOps.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,13 @@ def Yul_LogOp : Yul_Op<"log"> {
332332
let assemblyFormat = "$addr `,` $size oilist(`topics` `(` $topics `)` ) attr-dict";
333333
}
334334

335+
def Yul_SignExtendOp : Yul_Op<"signextend", [Pure]> {
336+
let summary = "Represents the `signextend` call in yul";
337+
let arguments = (ins I256:$val, I256:$off);
338+
let results = (outs I256:$out);
339+
let assemblyFormat = "$val `,` $off attr-dict";
340+
}
341+
335342
def Yul_SetImmutableOp : Yul_Op<"setimmutable"> {
336343
let summary = "Represents the `setimmutable` call in yul";
337344
let arguments = (ins I256:$addr, StrAttr:$name, I256:$val);

libsolidity/codegen/mlir/YulToMLIR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ void YulToMLIRPass::populateBuiltinGenMap() {
311311
};
312312
defSimpleBuiltinGen<AddModOp>("addmod");
313313
defSimpleBuiltinGen<MulModOp>("mulmod");
314+
defSimpleBuiltinGen<SignExtendOp>("signextend");
314315
defSimpleBuiltinGen<MLoadOp>("mload");
315316
defSimpleBuiltinGenNoRet<LoadImmutableOp>("loadimmutable");
316317
defSimpleBuiltinGenNoRet<MStoreOp>("mstore");
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: solc --strict-assembly --mlir-action=print-std-mlir --mlir-target=evm --mmlir --mlir-print-debuginfo %s | FileCheck %s
2+
3+
object "Test" {
4+
code {
5+
mstore(0, signextend(mload(0), mload(32)))
6+
return(0, 32)
7+
}
8+
}
9+
// NOTE: Assertions have been autogenerated by test/updFileCheckTest.py
10+
// CHECK: #Prague = #sol<EvmVersion Prague>
11+
// CHECK-NEXT: module @Test attributes {sol.evm_version = #Prague} {
12+
// CHECK-NEXT: func.func @".unreachable"() attributes {llvm.linkage = #llvm.linkage<private>, passthrough = ["nofree", "null_pointer_is_valid"]} {
13+
// CHECK-NEXT: llvm.unreachable loc(#loc1)
14+
// CHECK-NEXT: } loc(#loc)
15+
// CHECK-NEXT: func.func @__entry() attributes {llvm.linkage = #llvm.linkage<external>, passthrough = ["nofree", "null_pointer_is_valid"]} {
16+
// CHECK-NEXT: %c32_i256 = arith.constant 32 : i256 loc(#loc)
17+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc)
18+
// CHECK-NEXT: %0 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc2)
19+
// CHECK-NEXT: %1 = llvm.load %0 {alignment = 1 : i64} : !llvm.ptr<1> -> i256 loc(#loc2)
20+
// CHECK-NEXT: %2 = llvm.inttoptr %c32_i256 : i256 to !llvm.ptr<1> loc(#loc3)
21+
// CHECK-NEXT: %3 = llvm.load %2 {alignment = 1 : i64} : !llvm.ptr<1> -> i256 loc(#loc3)
22+
// CHECK-NEXT: %4 = "llvm.intrcall"(%1, %3) <{id = 3745 : i32, name = "evm.signextend"}> : (i256, i256) -> i256 loc(#loc4)
23+
// CHECK-NEXT: %5 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc5)
24+
// CHECK-NEXT: llvm.store %4, %5 {alignment = 1 : i64} : i256, !llvm.ptr<1> loc(#loc5)
25+
// CHECK-NEXT: %6 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
26+
// CHECK-NEXT: "llvm.intrcall"(%6, %c32_i256) <{id = 3735 : i32, name = "evm.return"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
27+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
28+
// CHECK-NEXT: llvm.unreachable loc(#loc)
29+
// CHECK-NEXT: } loc(#loc)
30+
// CHECK-NEXT: } loc(#loc)
31+
// CHECK-NEXT: #loc = loc(unknown)
32+
// CHECK-NEXT: #loc1 = loc({{.*}}:5:4)
33+
// CHECK-NEXT: #loc2 = loc({{.*}}:4:25)
34+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:35)
35+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:14)
36+
// CHECK-NEXT: #loc5 = loc({{.*}}:4:4)
37+
// CHECK-EMPTY:
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: solc --strict-assembly --mlir-action=print-init --mmlir --mlir-print-debuginfo %s | FileCheck %s
2+
3+
object "Test" {
4+
code {
5+
mstore(0, signextend(mload(0), mload(32)))
6+
}
7+
}
8+
// NOTE: Assertions have been autogenerated by test/updFileCheckTest.py
9+
// CHECK: #Prague = #sol<EvmVersion Prague>
10+
// CHECK-NEXT: module attributes {sol.evm_version = #Prague} {
11+
// CHECK-NEXT: yul.object @Test {
12+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc1)
13+
// CHECK-NEXT: %c0_i256_0 = arith.constant 0 : i256 loc(#loc2)
14+
// CHECK-NEXT: %0 = yul.mload %c0_i256_0 loc(#loc3)
15+
// CHECK-NEXT: %c32_i256 = arith.constant 32 : i256 loc(#loc4)
16+
// CHECK-NEXT: %1 = yul.mload %c32_i256 loc(#loc5)
17+
// CHECK-NEXT: %2 = yul.signextend %0, %1 loc(#loc6)
18+
// CHECK-NEXT: yul.mstore %c0_i256, %2 loc(#loc7)
19+
// CHECK-NEXT: } loc(#loc)
20+
// CHECK-NEXT: } loc(#loc)
21+
// CHECK-NEXT: #loc = loc(unknown)
22+
// CHECK-NEXT: #loc1 = loc({{.*}}:4:11)
23+
// CHECK-NEXT: #loc2 = loc({{.*}}:4:31)
24+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:25)
25+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:41)
26+
// CHECK-NEXT: #loc5 = loc({{.*}}:4:35)
27+
// CHECK-NEXT: #loc6 = loc({{.*}}:4:14)
28+
// CHECK-NEXT: #loc7 = loc({{.*}}:4:4)
29+
// CHECK-EMPTY:

0 commit comments

Comments
 (0)