Skip to content

Commit fcdf43e

Browse files
committed
[mlir][evm] Lower tload/tstore builtins
1 parent bba942c commit fcdf43e

File tree

7 files changed

+107
-0
lines changed

7 files changed

+107
-0
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@ Value evm::Builder::genStoragePtr(Value addr, std::optional<Location> locArg) {
148148
return b.create<LLVM::IntToPtrOp>(loc, storageAddrSpacePtrTy, addr);
149149
}
150150

151+
Value evm::Builder::genTStoragePtr(Value addr, std::optional<Location> locArg) {
152+
Location loc = locArg ? *locArg : defLoc;
153+
154+
auto tstorageAddrSpacePtrTy = LLVM::LLVMPointerType::get(
155+
b.getContext(), evm::AddrSpace_TransientStorage);
156+
return b.create<LLVM::IntToPtrOp>(loc, tstorageAddrSpacePtrTy, addr);
157+
}
158+
151159
Value evm::Builder::genCodePtr(Value addr, std::optional<Location> locArg) {
152160
Location loc = locArg ? *locArg : defLoc;
153161

libsolidity/codegen/mlir/Target/EVM/Util.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ class Builder {
164164
genStoragePtr(mlir::Value addr,
165165
std::optional<mlir::Location> locArg = std::nullopt);
166166

167+
/// Generates a pointer to the address in the transient storage.
168+
mlir::Value
169+
genTStoragePtr(mlir::Value addr,
170+
std::optional<mlir::Location> locArg = std::nullopt);
171+
167172
/// Generates a pointer to the address in the code.
168173
mlir::Value genCodePtr(mlir::Value addr,
169174
std::optional<mlir::Location> locArg = std::nullopt);

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,34 @@ struct SStoreOpLowering : public OpRewritePattern<yul::SStoreOp> {
248248
}
249249
};
250250

251+
struct TLoadOpLowering : public OpRewritePattern<yul::TLoadOp> {
252+
using OpRewritePattern<yul::TLoadOp>::OpRewritePattern;
253+
254+
LogicalResult matchAndRewrite(yul::TLoadOp op,
255+
PatternRewriter &r) const override {
256+
evm::Builder evmB(r, op->getLoc());
257+
258+
Value ptr = evmB.genTStoragePtr(op.getAddr());
259+
r.replaceOpWithNewOp<LLVM::LoadOp>(op, r.getIntegerType(256), ptr,
260+
evm::getAlignment(ptr));
261+
return success();
262+
}
263+
};
264+
265+
struct TStoreOpLowering : public OpRewritePattern<yul::TStoreOp> {
266+
using OpRewritePattern<yul::TStoreOp>::OpRewritePattern;
267+
268+
LogicalResult matchAndRewrite(yul::TStoreOp op,
269+
PatternRewriter &r) const override {
270+
evm::Builder evmB(r, op->getLoc());
271+
272+
Value ptr = evmB.genTStoragePtr(op.getAddr());
273+
r.replaceOpWithNewOp<LLVM::StoreOp>(op, op.getVal(), ptr,
274+
evm::getAlignment(ptr));
275+
return success();
276+
}
277+
};
278+
251279
struct DataOffsetOpLowering : public OpRewritePattern<yul::DataOffsetOp> {
252280
using OpRewritePattern<yul::DataOffsetOp>::OpRewritePattern;
253281

@@ -711,6 +739,8 @@ void evm::populateYulPats(RewritePatternSet &pats) {
711739
ReturnDataCopyOpLowering,
712740
SLoadOpLowering,
713741
SStoreOpLowering,
742+
TLoadOpLowering,
743+
TStoreOpLowering,
714744
DataOffsetOpLowering,
715745
DataSizeOpLowering,
716746
CodeSizeOpLowering,

libsolidity/codegen/mlir/Yul/YulOps.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,19 @@ def Yul_SStoreOp : Yul_Op<"sstore"> {
217217
let assemblyFormat = "$addr `,` $val attr-dict";
218218
}
219219

220+
def Yul_TLoadOp : Yul_Op<"tload"> {
221+
let summary = "Represents the `tload` call in yul";
222+
let arguments = (ins I256:$addr);
223+
let results = (outs I256:$out);
224+
let assemblyFormat = "$addr attr-dict";
225+
}
226+
227+
def Yul_TStoreOp : Yul_Op<"tstore"> {
228+
let summary = "Represents the `tstore` call in yul";
229+
let arguments = (ins I256:$addr, I256:$val);
230+
let assemblyFormat = "$addr `,` $val attr-dict";
231+
}
232+
220233
// TODO: Support symbolic references to objects outside the current symbol table
221234
// (including ones outside the translation unit) using SymbolRefAttr instead of
222235
// FlatSymbolRefAttr

libsolidity/codegen/mlir/YulToMLIR.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ void YulToMLIRPass::populateBuiltinGenMap() {
313313
defSimpleBuiltinGen<Create2Op>("create2");
314314
defSimpleBuiltinGen<SLoadOp>("sload");
315315
defSimpleBuiltinGenNoRet<SStoreOp>("sstore");
316+
defSimpleBuiltinGen<TLoadOp>("tload");
317+
defSimpleBuiltinGenNoRet<TStoreOp>("tstore");
316318
defSimpleBuiltinGenNoRet<ReturnOp>("return");
317319
defSimpleBuiltinGenNoRet<RevertOp>("revert");
318320
defSimpleBuiltinGenNoRet<StopOp>("stop");
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
tstore(0, tload(1))
6+
}
7+
}
8+
// NOTE: Assertions have been autogenerated by test/updFileCheckTest.py
9+
// CHECK: #Prague = #sol<EvmVersion Prague>
10+
// CHECK-NEXT: module @Test attributes {sol.evm_version = #Prague} {
11+
// CHECK-NEXT: func.func @__entry() attributes {llvm.linkage = #llvm.linkage<external>, passthrough = ["nofree", "null_pointer_is_valid"]} {
12+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc1)
13+
// CHECK-NEXT: %c1_i256 = arith.constant 1 : i256 loc(#loc2)
14+
// CHECK-NEXT: %0 = llvm.inttoptr %c1_i256 : i256 to !llvm.ptr<6> loc(#loc3)
15+
// CHECK-NEXT: %1 = llvm.load %0 {alignment = 1 : i64} : !llvm.ptr<6> -> i256 loc(#loc3)
16+
// CHECK-NEXT: %2 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<6> loc(#loc4)
17+
// CHECK-NEXT: llvm.store %1, %2 {alignment = 1 : i64} : i256, !llvm.ptr<6> loc(#loc4)
18+
// CHECK-NEXT: llvm.unreachable loc(#loc)
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:20)
24+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:14)
25+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:4)
26+
// CHECK-EMPTY:
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: solc --strict-assembly --mlir-action=print-init --mmlir --mlir-print-debuginfo %s | FileCheck %s
2+
3+
object "Test" {
4+
code {
5+
tstore(0, tload(1))
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: %c1_i256 = arith.constant 1 : i256 loc(#loc2)
14+
// CHECK-NEXT: %0 = yul.tload %c1_i256 loc(#loc3)
15+
// CHECK-NEXT: yul.tstore %c0_i256, %0 loc(#loc4)
16+
// CHECK-NEXT: } loc(#loc)
17+
// CHECK-NEXT: } loc(#loc)
18+
// CHECK-NEXT: #loc = loc(unknown)
19+
// CHECK-NEXT: #loc1 = loc({{.*}}:4:11)
20+
// CHECK-NEXT: #loc2 = loc({{.*}}:4:20)
21+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:14)
22+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:4)
23+
// CHECK-EMPTY:

0 commit comments

Comments
 (0)