Skip to content

Commit 1d6ac85

Browse files
committed
[mlir][evm] Lower signextend builtin
1 parent 700eee7 commit 1d6ac85

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
@@ -218,6 +218,22 @@ struct MulModOpLowering : public OpRewritePattern<yul::MulModOp> {
218218
}
219219
};
220220

221+
struct SignExtendOpLowering : public OpRewritePattern<yul::SignExtendOp> {
222+
using OpRewritePattern<yul::SignExtendOp>::OpRewritePattern;
223+
224+
LogicalResult matchAndRewrite(yul::SignExtendOp op,
225+
PatternRewriter &r) const override {
226+
evm::Builder evmB(r, op.getLoc());
227+
228+
r.replaceOpWithNewOp<LLVM::IntrCallOp>(
229+
op, llvm::Intrinsic::evm_signextend,
230+
/*resTy=*/r.getIntegerType(256),
231+
/*ins=*/ValueRange{op.getVal(), op.getOff()}, "evm.signextend");
232+
233+
return success();
234+
}
235+
};
236+
221237
struct LogOpLowering : public OpRewritePattern<yul::LogOp> {
222238
using OpRewritePattern<yul::LogOp>::OpRewritePattern;
223239

@@ -895,6 +911,7 @@ void evm::populateYulPats(RewritePatternSet &pats) {
895911
ShrOpLowering,
896912
SarOpLowering,
897913
ExpOpLowering,
914+
SignExtendOpLowering,
898915
LogOpLowering,
899916
AddressOpLowering,
900917
CallerOpLowering,

libsolidity/codegen/mlir/Yul/YulOps.td

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

384+
def Yul_SignExtendOp : Yul_Op<"signextend", [Pure]> {
385+
let summary = "Represents the `signextend` call in yul";
386+
let arguments = (ins I256:$val, I256:$off);
387+
let results = (outs I256:$out);
388+
let assemblyFormat = "$val `,` $off attr-dict";
389+
}
390+
384391
def Yul_SetImmutableOp : Yul_Op<"setimmutable"> {
385392
let summary = "Represents the `setimmutable` call in yul";
386393
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
@@ -315,6 +315,7 @@ void YulToMLIRPass::populateBuiltinGenMap() {
315315
};
316316
defSimpleBuiltinGen<AddModOp>("addmod");
317317
defSimpleBuiltinGen<MulModOp>("mulmod");
318+
defSimpleBuiltinGen<SignExtendOp>("signextend");
318319
defSimpleBuiltinGen<MLoadOp>("mload");
319320
defSimpleBuiltinGenNoRet<LoadImmutableOp>("loadimmutable");
320321
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)