@@ -1968,9 +1968,12 @@ SolidityToMLIRPass::genExprs(FunctionCall const &call) {
19681968
19691969 // Keep the creation result typed as the FE return contract type so
19701970 // payability is preserved (contract vs contract<payable>).
1971- resVals. push_back ( b.create <mlir::sol::NewOp>(
1971+ auto newOp = b.create <mlir::sol::NewOp>(
19721972 loc, getType (calleeTy->returnParameterTypes ().front ()), objName, value,
1973- salt, args));
1973+ salt, args);
1974+ if (call.annotation ().tryCall )
1975+ newOp.setTryCall (true );
1976+ resVals.push_back (newOp.getResult ());
19741977 return resVals;
19751978 }
19761979
@@ -2712,14 +2715,35 @@ void SolidityToMLIRPass::lower(ForStatement const &forStmt) {
27122715void SolidityToMLIRPass::lower (TryStatement const &tryStmt) {
27132716 mlir::Location loc = getLoc (tryStmt);
27142717
2715- // TODO: sol.new
2716- // `try` is the one frontend-level construct that needs the otherwise-hidden
2717- // status of a high-level external call. Lower it through `genExternalCall`
2718- // which exposes both status and results explicitly.
27192718 auto const *callExpr =
27202719 dynamic_cast <FunctionCall const *>(&tryStmt.externalCall ());
27212720 assert (callExpr && " Expected FunctionCall expression in TryStatement" );
2722- auto [status, results] = genExternalCall (*callExpr);
2721+ auto const *calleeTy = dynamic_cast <FunctionType const *>(
2722+ callExpr->expression ().annotation ().type );
2723+ assert (calleeTy);
2724+
2725+ mlir::Value status;
2726+ mlir::SmallVector<mlir::Value> results;
2727+ if (calleeTy->kind () == FunctionType::Kind::Creation) {
2728+ // genExprs propagates tryCall onto the sol.new (suppressing the
2729+ // forwarding-revert); status is `addr != 0`
2730+ results.append (genExprs (*callExpr));
2731+ assert (results.size () == 1 && " new returns exactly one contract value" );
2732+ auto addrTy =
2733+ mlir::sol::AddressType::get (b.getContext (), /* payable=*/ false );
2734+ auto ui160Ty = b.getIntegerType (160 , /* isSigned=*/ false );
2735+ mlir::Value addr =
2736+ b.create <mlir::sol::AddressCastOp>(loc, addrTy, results.front ());
2737+ mlir::Value addrUi = b.create <mlir::sol::AddressCastOp>(loc, ui160Ty, addr);
2738+ mlir::Value zero = genUnsignedConst (0 , /* numBits=*/ 160 , loc);
2739+ status = b.create <mlir::sol::CmpOp>(loc, mlir::sol::CmpPredicate::ne,
2740+ addrUi, zero);
2741+ } else {
2742+ auto extResult = genExternalCall (*callExpr);
2743+ status = extResult.status ;
2744+ results = std::move (extResult.results );
2745+ }
2746+
27232747 auto tryOp = b.create <mlir::sol::TryOp>(loc, status);
27242748
27252749 // Lower success clause.
0 commit comments