Skip to content

Commit 595e744

Browse files
committed
[mlir][Sol] Lower blockhash, blobhash and selfdestruct builtins
1 parent 9a86bcb commit 595e744

7 files changed

Lines changed: 460 additions & 131 deletions

File tree

libsolidity/codegen/mlir/SolidityToMLIR.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,6 +2253,29 @@ SolidityToMLIRPass::genExprs(FunctionCall const &call) {
22532253
resVals.push_back(b.create<mlir::sol::GasLeftOp>(loc));
22542254
return resVals;
22552255

2256+
case FunctionType::Kind::BlockHash: {
2257+
mlir::Value arg =
2258+
genRValExpr(*astArgs[0], getType(calleeTy->parameterTypes()[0]));
2259+
resVals.push_back(b.create<mlir::sol::BlockHashOp>(
2260+
loc, getType(calleeTy->returnParameterTypes()[0]), arg));
2261+
return resVals;
2262+
}
2263+
2264+
case FunctionType::Kind::BlobHash: {
2265+
mlir::Value arg =
2266+
genRValExpr(*astArgs[0], getType(calleeTy->parameterTypes()[0]));
2267+
resVals.push_back(b.create<mlir::sol::BlobHashOp>(
2268+
loc, getType(calleeTy->returnParameterTypes()[0]), arg));
2269+
return resVals;
2270+
}
2271+
2272+
case FunctionType::Kind::Selfdestruct: {
2273+
mlir::Value arg =
2274+
genRValExpr(*astArgs[0], getType(calleeTy->parameterTypes()[0]));
2275+
b.create<mlir::sol::SelfdestructOp>(loc, arg);
2276+
return resVals;
2277+
}
2278+
22562279
default:
22572280
break;
22582281
}

libsolidity/codegen/mlir/YulToMLIR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ void YulToMLIRPass::populateBuiltinGenMap() {
348348
defSimpleBuiltinGen<GasPriceOp>("gasprice");
349349
defSimpleBuiltinGen<BlockHashOp>("blockhash");
350350
defSimpleBuiltinGen<BlobHashOp>("blobhash");
351+
defSimpleBuiltinGenNoRet<SelfDestructOp>("selfdestruct");
351352
defSimpleBuiltinGen<CoinBaseOp>("coinbase");
352353
defSimpleBuiltinGen<TimeStampOp>("timestamp");
353354
defSimpleBuiltinGen<NumberOp>("number");
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// RUN: solc --mlir-action=print-std-mlir --mlir-target=evm --mmlir --mlir-print-debuginfo %s | FileCheck %s
2+
3+
contract C {
4+
function kill(address payable r) public { selfdestruct(r); }
5+
}
6+
// NOTE: Assertions have been autogenerated by test/updFileCheckTest.py
7+
// CHECK: #Default = #sol<RevertStrings Default>
8+
// CHECK-NEXT: #Osaka = #sol<EvmVersion Osaka>
9+
// CHECK-NEXT: #loc3 = loc({{.*}}:3:16)
10+
// CHECK-NEXT: module @C_11 attributes {llvm.data_layout = "E-p:256:256-i256:256:256-S256-a:256:256", llvm.target_triple = "evm-unknown-unknown", sol.evm_version = #Osaka, sol.revert_strings = #Default} {
11+
// CHECK-NEXT: func.func @".unreachable"() attributes {llvm.linkage = #llvm.linkage<private>, passthrough = ["nofree", "null_pointer_is_valid"]} {
12+
// CHECK-NEXT: llvm.unreachable loc(#loc1)
13+
// CHECK-NEXT: } loc(#loc)
14+
// CHECK-NEXT: func.func @__entry() attributes {llvm.linkage = #llvm.linkage<external>, passthrough = ["nofree", "null_pointer_is_valid"]} {
15+
// CHECK-NEXT: %c36_i256 = arith.constant 36 : i256 loc(#loc)
16+
// CHECK-NEXT: %c65_i256 = arith.constant 65 : i256 loc(#loc)
17+
// CHECK-NEXT: %c4_i256 = arith.constant 4 : i256 loc(#loc)
18+
// CHECK-NEXT: %c35408467139433450592217433187231851964531694900788300625387963629091585785856_i256 = arith.constant 35408467139433450592217433187231851964531694900788300625387963629091585785856 : i256 loc(#loc)
19+
// CHECK-NEXT: %c18446744073709551615_i256 = arith.constant 18446744073709551615 : i256 loc(#loc)
20+
// CHECK-NEXT: %c-32_i256 = arith.constant -32 : i256 loc(#loc)
21+
// CHECK-NEXT: %c31_i256 = arith.constant 31 : i256 loc(#loc)
22+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc)
23+
// CHECK-NEXT: %c128_i256 = arith.constant 128 : i256 loc(#loc1)
24+
// CHECK-NEXT: %c64_i256 = arith.constant 64 : i256 loc(#loc)
25+
// CHECK-NEXT: %0 = llvm.inttoptr %c64_i256 : i256 to !llvm.ptr<1> loc(#loc1)
26+
// CHECK-NEXT: llvm.store %c128_i256, %0 {alignment = 1 : i64} : i256, !llvm.ptr<1> loc(#loc1)
27+
// CHECK-NEXT: %1 = "llvm.intrcall"() <{id = 4040 : i32, name = "evm.callvalue"}> : () -> i256 loc(#loc1)
28+
// CHECK-NEXT: %2 = arith.cmpi ne, %1, %c0_i256 : i256 loc(#loc1)
29+
// CHECK-NEXT: cf.cond_br %2, ^bb1, ^bb2 loc(#loc1)
30+
// CHECK-NEXT: ^bb1: // pred: ^bb0
31+
// CHECK-NEXT: %3 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
32+
// CHECK-NEXT: "llvm.intrcall"(%3, %c0_i256) <{id = 4080 : i32, name = "evm.revert"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
33+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
34+
// CHECK-NEXT: cf.br ^bb2 loc(#loc1)
35+
// CHECK-NEXT: ^bb2: // 2 preds: ^bb0, ^bb1
36+
// CHECK-NEXT: %4 = "llvm.intrcall"() <{id = 4047 : i32, metadata = ["C_11"], name = "evm.datasize"}> : () -> i256 loc(#loc1)
37+
// CHECK-NEXT: %5 = "llvm.intrcall"() <{id = 4042 : i32, name = "evm.codesize"}> : () -> i256 loc(#loc1)
38+
// CHECK-NEXT: %6 = arith.subi %5, %4 : i256 loc(#loc1)
39+
// CHECK-NEXT: %7 = llvm.inttoptr %c64_i256 : i256 to !llvm.ptr<1> loc(#loc1)
40+
// CHECK-NEXT: %8 = llvm.load %7 {alignment = 1 : i64} : !llvm.ptr<1> -> i256 loc(#loc1)
41+
// CHECK-NEXT: %9 = arith.addi %6, %c31_i256 : i256 loc(#loc1)
42+
// CHECK-NEXT: %10 = arith.andi %9, %c-32_i256 : i256 loc(#loc1)
43+
// CHECK-NEXT: %11 = arith.addi %8, %10 : i256 loc(#loc1)
44+
// CHECK-NEXT: %12 = arith.cmpi ugt, %11, %c18446744073709551615_i256 : i256 loc(#loc1)
45+
// CHECK-NEXT: %13 = arith.cmpi ult, %11, %8 : i256 loc(#loc1)
46+
// CHECK-NEXT: %14 = arith.ori %12, %13 : i1 loc(#loc1)
47+
// CHECK-NEXT: cf.cond_br %14, ^bb3, ^bb4 loc(#loc1)
48+
// CHECK-NEXT: ^bb3: // pred: ^bb2
49+
// CHECK-NEXT: %15 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
50+
// CHECK-NEXT: llvm.store %c35408467139433450592217433187231851964531694900788300625387963629091585785856_i256, %15 {alignment = 1 : i64} : i256, !llvm.ptr<1> loc(#loc1)
51+
// CHECK-NEXT: %16 = llvm.inttoptr %c4_i256 : i256 to !llvm.ptr<1> loc(#loc1)
52+
// CHECK-NEXT: llvm.store %c65_i256, %16 {alignment = 1 : i64} : i256, !llvm.ptr<1> loc(#loc1)
53+
// CHECK-NEXT: %17 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
54+
// CHECK-NEXT: "llvm.intrcall"(%17, %c36_i256) <{id = 4080 : i32, name = "evm.revert"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
55+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
56+
// CHECK-NEXT: cf.br ^bb4 loc(#loc1)
57+
// CHECK-NEXT: ^bb4: // 2 preds: ^bb2, ^bb3
58+
// CHECK-NEXT: %18 = llvm.inttoptr %c64_i256 : i256 to !llvm.ptr<1> loc(#loc1)
59+
// CHECK-NEXT: llvm.store %11, %18 {alignment = 1 : i64} : i256, !llvm.ptr<1> loc(#loc1)
60+
// CHECK-NEXT: %19 = llvm.inttoptr %8 : i256 to !llvm.ptr<1> loc(#loc1)
61+
// CHECK-NEXT: %20 = llvm.inttoptr %4 : i256 to !llvm.ptr<4> loc(#loc1)
62+
// CHECK-NEXT: "llvm.intr.memcpy"(%19, %20, %6) <{isVolatile = false}> : (!llvm.ptr<1>, !llvm.ptr<4>, i256) -> () loc(#loc1)
63+
// CHECK-NEXT: call @C_11() : () -> () loc(#loc1)
64+
// CHECK-NEXT: %21 = llvm.inttoptr %c64_i256 : i256 to !llvm.ptr<1> loc(#loc1)
65+
// CHECK-NEXT: %22 = llvm.load %21 {alignment = 1 : i64} : !llvm.ptr<1> -> i256 loc(#loc1)
66+
// CHECK-NEXT: %23 = "llvm.intrcall"() <{id = 4046 : i32, metadata = ["C_11_deployed"], name = "evm.dataoffset"}> : () -> i256 loc(#loc1)
67+
// CHECK-NEXT: %24 = "llvm.intrcall"() <{id = 4047 : i32, metadata = ["C_11_deployed"], name = "evm.datasize"}> : () -> i256 loc(#loc1)
68+
// CHECK-NEXT: %25 = llvm.inttoptr %22 : i256 to !llvm.ptr<1> loc(#loc1)
69+
// CHECK-NEXT: %26 = llvm.inttoptr %23 : i256 to !llvm.ptr<4> loc(#loc1)
70+
// CHECK-NEXT: "llvm.intr.memcpy"(%25, %26, %24) <{isVolatile = false}> : (!llvm.ptr<1>, !llvm.ptr<4>, i256) -> () loc(#loc1)
71+
// CHECK-NEXT: %27 = llvm.inttoptr %22 : i256 to !llvm.ptr<1> loc(#loc1)
72+
// CHECK-NEXT: "llvm.intrcall"(%27, %24) <{id = 4078 : i32, name = "evm.return"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
73+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
74+
// CHECK-NEXT: llvm.unreachable loc(#loc1)
75+
// CHECK-NEXT: } loc(#loc)
76+
// CHECK-NEXT: func.func @C_11() attributes {llvm.linkage = #llvm.linkage<private>, passthrough = ["nofree", "null_pointer_is_valid"]} {
77+
// CHECK-NEXT: return loc(#loc1)
78+
// CHECK-NEXT: } loc(#loc1)
79+
// CHECK-NEXT: module @C_11_deployed attributes {llvm.data_layout = "E-p:256:256-i256:256:256-S256-a:256:256", llvm.target_triple = "evm-unknown-unknown", sol.evm_version = #Osaka, sol.revert_strings = #Default} {
80+
// CHECK-NEXT: func.func @".unreachable"() attributes {llvm.linkage = #llvm.linkage<private>, passthrough = ["nofree", "null_pointer_is_valid"]} {
81+
// CHECK-NEXT: llvm.unreachable loc(#loc1)
82+
// CHECK-NEXT: } loc(#loc1)
83+
// CHECK-NEXT: func.func @__entry() attributes {llvm.linkage = #llvm.linkage<external>, passthrough = ["nofree", "null_pointer_is_valid"]} {
84+
// CHECK-NEXT: %c1461501637330902918203684832716283019655932542975_i256 = arith.constant 1461501637330902918203684832716283019655932542975 : i256 loc(#loc)
85+
// CHECK-NEXT: %c32_i256 = arith.constant 32 : i256 loc(#loc)
86+
// CHECK-NEXT: %c224_i256 = arith.constant 224 : i256 loc(#loc)
87+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc)
88+
// CHECK-NEXT: %c4_i256 = arith.constant 4 : i256 loc(#loc)
89+
// CHECK-NEXT: %c128_i256 = arith.constant 128 : i256 loc(#loc1)
90+
// CHECK-NEXT: %c64_i256 = arith.constant 64 : i256 loc(#loc)
91+
// CHECK-NEXT: %0 = llvm.inttoptr %c64_i256 : i256 to !llvm.ptr<1> loc(#loc1)
92+
// CHECK-NEXT: llvm.store %c128_i256, %0 {alignment = 1 : i64} : i256, !llvm.ptr<1> loc(#loc1)
93+
// CHECK-NEXT: %1 = "llvm.intrcall"() <{id = 4038 : i32, name = "evm.calldatasize"}> : () -> i256 loc(#loc1)
94+
// CHECK-NEXT: %2 = arith.cmpi uge, %1, %c4_i256 : i256 loc(#loc1)
95+
// CHECK-NEXT: cf.cond_br %2, ^bb1, ^bb9 loc(#loc1)
96+
// CHECK-NEXT: ^bb1: // pred: ^bb0
97+
// CHECK-NEXT: %3 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<2> loc(#loc1)
98+
// CHECK-NEXT: %4 = llvm.load %3 {alignment = 1 : i64} : !llvm.ptr<2> -> i256 loc(#loc1)
99+
// CHECK-NEXT: %5 = arith.shrui %4, %c224_i256 : i256 loc(#loc1)
100+
// CHECK-NEXT: cf.switch %5 : i256, [
101+
// CHECK-NEXT: default: ^bb9,
102+
// CHECK-NEXT: 3421548736: ^bb2
103+
// CHECK-NEXT: ] loc(#loc1)
104+
// CHECK-NEXT: ^bb2: // pred: ^bb1
105+
// CHECK-NEXT: %6 = "llvm.intrcall"() <{id = 4040 : i32, name = "evm.callvalue"}> : () -> i256 loc(#loc1)
106+
// CHECK-NEXT: %7 = arith.cmpi ne, %6, %c0_i256 : i256 loc(#loc1)
107+
// CHECK-NEXT: cf.cond_br %7, ^bb3, ^bb4 loc(#loc1)
108+
// CHECK-NEXT: ^bb3: // pred: ^bb2
109+
// CHECK-NEXT: %8 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
110+
// CHECK-NEXT: "llvm.intrcall"(%8, %c0_i256) <{id = 4080 : i32, name = "evm.revert"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
111+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
112+
// CHECK-NEXT: cf.br ^bb4 loc(#loc1)
113+
// CHECK-NEXT: ^bb4: // 2 preds: ^bb2, ^bb3
114+
// CHECK-NEXT: %9 = arith.subi %1, %c4_i256 : i256 loc(#loc1)
115+
// CHECK-NEXT: %10 = arith.cmpi slt, %9, %c32_i256 : i256 loc(#loc1)
116+
// CHECK-NEXT: cf.cond_br %10, ^bb5, ^bb6 loc(#loc1)
117+
// CHECK-NEXT: ^bb5: // pred: ^bb4
118+
// CHECK-NEXT: %11 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
119+
// CHECK-NEXT: "llvm.intrcall"(%11, %c0_i256) <{id = 4080 : i32, name = "evm.revert"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
120+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
121+
// CHECK-NEXT: cf.br ^bb6 loc(#loc1)
122+
// CHECK-NEXT: ^bb6: // 2 preds: ^bb4, ^bb5
123+
// CHECK-NEXT: %12 = llvm.inttoptr %c4_i256 : i256 to !llvm.ptr<2> loc(#loc1)
124+
// CHECK-NEXT: %13 = llvm.load %12 {alignment = 1 : i64} : !llvm.ptr<2> -> i256 loc(#loc1)
125+
// CHECK-NEXT: %14 = arith.andi %13, %c1461501637330902918203684832716283019655932542975_i256 : i256 loc(#loc1)
126+
// CHECK-NEXT: %15 = arith.cmpi ne, %13, %14 : i256 loc(#loc1)
127+
// CHECK-NEXT: cf.cond_br %15, ^bb7, ^bb8 loc(#loc1)
128+
// CHECK-NEXT: ^bb7: // pred: ^bb6
129+
// CHECK-NEXT: %16 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
130+
// CHECK-NEXT: "llvm.intrcall"(%16, %c0_i256) <{id = 4080 : i32, name = "evm.revert"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
131+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
132+
// CHECK-NEXT: cf.br ^bb8 loc(#loc1)
133+
// CHECK-NEXT: ^bb8: // 2 preds: ^bb6, ^bb7
134+
// CHECK-NEXT: call @kill_10(%14) : (i256) -> () loc(#loc1)
135+
// CHECK-NEXT: %17 = llvm.inttoptr %c64_i256 : i256 to !llvm.ptr<1> loc(#loc1)
136+
// CHECK-NEXT: %18 = llvm.load %17 {alignment = 1 : i64} : !llvm.ptr<1> -> i256 loc(#loc1)
137+
// CHECK-NEXT: %19 = llvm.inttoptr %18 : i256 to !llvm.ptr<1> loc(#loc1)
138+
// CHECK-NEXT: "llvm.intrcall"(%19, %c0_i256) <{id = 4078 : i32, name = "evm.return"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
139+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
140+
// CHECK-NEXT: cf.br ^bb9 loc(#loc1)
141+
// CHECK-NEXT: ^bb9: // 3 preds: ^bb0, ^bb1, ^bb8
142+
// CHECK-NEXT: %20 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
143+
// CHECK-NEXT: "llvm.intrcall"(%20, %c0_i256) <{id = 4080 : i32, name = "evm.revert"}> : (!llvm.ptr<1>, i256) -> () loc(#loc1)
144+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc1)
145+
// CHECK-NEXT: llvm.unreachable loc(#loc1)
146+
// CHECK-NEXT: } loc(#loc1)
147+
// CHECK-NEXT: func.func @kill_10(%arg0: i256 loc({{.*}}:3:16)) attributes {llvm.linkage = #llvm.linkage<private>, passthrough = ["nofree", "null_pointer_is_valid"]} {
148+
// CHECK-NEXT: %c1461501637330902918203684832716283019655932542975_i256 = arith.constant 1461501637330902918203684832716283019655932542975 : i256 loc(#loc)
149+
// CHECK-NEXT: %c1_i256 = arith.constant 1 : i256 loc(#loc3)
150+
// CHECK-NEXT: %0 = llvm.alloca %c1_i256 x i256 : (i256) -> !llvm.ptr loc(#loc3)
151+
// CHECK-NEXT: llvm.store %arg0, %0 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc3)
152+
// CHECK-NEXT: %1 = llvm.load %0 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc4)
153+
// CHECK-NEXT: %2 = arith.andi %1, %c1461501637330902918203684832716283019655932542975_i256 : i256 loc(#loc5)
154+
// CHECK-NEXT: "llvm.intrcall"(%2) <{id = 4084 : i32, name = "evm.selfdestruct"}> : (i256) -> () loc(#loc5)
155+
// CHECK-NEXT: call @".unreachable"() : () -> () loc(#loc5)
156+
// CHECK-NEXT: return loc(#loc2)
157+
// CHECK-NEXT: } loc(#loc2)
158+
// CHECK-NEXT: } loc(#loc1)
159+
// CHECK-NEXT: } loc(#loc)
160+
// CHECK-NEXT: #loc = loc(unknown)
161+
// CHECK-NEXT: #loc1 = loc({{.*}}:2:0)
162+
// CHECK-NEXT: #loc2 = loc({{.*}}:3:2)
163+
// CHECK-NEXT: #loc4 = loc({{.*}}:3:57)
164+
// CHECK-NEXT: #loc5 = loc({{.*}}:3:44)
165+
// CHECK-EMPTY:

0 commit comments

Comments
 (0)