@@ -351,6 +351,9 @@ class SolidityToMLIRPass {
351351 // / Returns the mlir expression for the binary operation.
352352 mlir::Value genExpr (BinaryOperation const &binOp);
353353
354+ // / Returns the mlir expressions for the conditional (ternary) operation.
355+ mlir::SmallVector<mlir::Value> genExprs (Conditional const &cond);
356+
354357 // / Returns the mlir expression for the call.
355358 mlir::SmallVector<mlir::Value> genExprs (FunctionCall const &call);
356359
@@ -369,8 +372,10 @@ class SolidityToMLIRPass {
369372 // / to the corresponding mlir type of `resTy`.
370373 mlir::Value genRValExpr (Expression const &expr,
371374 std::optional<mlir::Type> resTy = std::nullopt );
372- mlir::Value genRValExpr (mlir::Value val, mlir::Location loc);
373- mlir::SmallVector<mlir::Value> genRValExprs (Expression const &expr);
375+ mlir::Value genRValExpr (mlir::Value val, mlir::Location loc,
376+ std::optional<mlir::Type> resTy = std::nullopt );
377+ mlir::SmallVector<mlir::Value> genRValExprs (Expression const &expr,
378+ mlir::TypeRange resTys = {});
374379
375380 // / Generates an ir that assigns `rhs` to `lhs`.
376381 void genAssign (mlir::Value lhs, mlir::Value rhs, mlir::Location loc);
@@ -849,6 +854,31 @@ mlir::Value SolidityToMLIRPass::genExpr(UnaryOperation const &unaryOp) {
849854 b.create <mlir::sol::ConstantOp>(loc, b.getIntegerAttr (mlirTy, 0 ));
850855 return genBinExpr (Token::Sub, zero, expr, loc);
851856 }
857+ // Logical not
858+ case Token::Not: {
859+ mlir::Value expr = genRValExpr (unaryOp.subExpression ());
860+ mlir::Value zero = b.create <mlir::sol::ConstantOp>(
861+ loc, b.getIntegerAttr (expr.getType (), 0 ));
862+ return b.create <mlir::sol::CmpOp>(loc, mlir::sol::CmpPredicate::eq, expr,
863+ zero);
864+ }
865+ // Bitwise not (~x == x ^ -1)
866+ case Token::BitNot: {
867+ mlir::Value expr = genRValExpr (unaryOp.subExpression ());
868+
869+ // Convert bytes to int if needed.
870+ if (auto bytesTy = mlir::dyn_cast<mlir::sol::BytesType>(expr.getType ())) {
871+ mlir::Type intTy =
872+ b.getIntegerType (bytesTy.getSize () * 8 , /* isSigned=*/ false );
873+ expr = genCast (expr, intTy);
874+ }
875+
876+ auto intTy = mlir::cast<mlir::IntegerType>(expr.getType ());
877+ mlir::Value allOnes = b.create <mlir::sol::ConstantOp>(
878+ loc,
879+ b.getIntegerAttr (intTy, llvm::APInt::getAllOnes (intTy.getWidth ())));
880+ return b.create <mlir::sol::XorOp>(loc, expr, allOnes);
881+ }
852882 default :
853883 break ;
854884 }
@@ -910,6 +940,38 @@ mlir::Value SolidityToMLIRPass::genExpr(BinaryOperation const &binOp) {
910940 return genBinExpr (binOp.getOperator (), lhs, rhs, loc);
911941}
912942
943+ mlir::SmallVector<mlir::Value>
944+ SolidityToMLIRPass::genExprs (Conditional const &cond) {
945+ mlir::Location loc = getLoc (cond);
946+ mlir::Value condVal = genRValExpr (cond.condition ());
947+
948+ // Get result types - could be single type or tuple.
949+ mlir::SmallVector<mlir::Type> resTys;
950+ if (TupleType const *tupleTy =
951+ dynamic_cast <TupleType const *>(cond.annotation ().type )) {
952+ for (const Type *astTy : tupleTy->components ())
953+ resTys.push_back (getType (astTy));
954+ } else {
955+ resTys.push_back (getType (cond.annotation ().type ));
956+ }
957+
958+ auto ifOp =
959+ b.create <mlir::scf::IfOp>(loc, resTys, condVal, /* withElse=*/ true );
960+ mlir::OpBuilder::InsertionGuard guard (b);
961+
962+ // True branch
963+ b.setInsertionPointToStart (&ifOp.getThenRegion ().front ());
964+ b.create <mlir::scf::YieldOp>(loc,
965+ genRValExprs (cond.trueExpression (), resTys));
966+
967+ // False branch
968+ b.setInsertionPointToStart (&ifOp.getElseRegion ().front ());
969+ b.create <mlir::scf::YieldOp>(loc,
970+ genRValExprs (cond.falseExpression (), resTys));
971+
972+ return ifOp.getResults ();
973+ }
974+
913975mlir::Value SolidityToMLIRPass::genExpr (IndexAccess const &idxAcc) {
914976 mlir::Location loc = getLoc (idxAcc);
915977
@@ -1935,6 +1997,13 @@ mlir::Value SolidityToMLIRPass::genLValExpr(Expression const &expr) {
19351997 return {};
19361998 }
19371999
2000+ // Conditional (ternary operator)
2001+ if (const auto *cond = dynamic_cast <Conditional const *>(&expr)) {
2002+ mlir::SmallVector<mlir::Value> exprs = genExprs (*cond);
2003+ assert (exprs.size () == 1 );
2004+ return exprs[0 ];
2005+ }
2006+
19382007 llvm_unreachable (" NYI" );
19392008}
19402009
@@ -1948,38 +2017,46 @@ SolidityToMLIRPass::genLValExprs(Expression const &expr) {
19482017 if (const auto *call = dynamic_cast <FunctionCall const *>(&expr))
19492018 return genExprs (*call);
19502019
2020+ // Conditional (ternary)
2021+ if (const auto *cond = dynamic_cast <Conditional const *>(&expr))
2022+ return genExprs (*cond);
2023+
19512024 mlir::SmallVector<mlir::Value, 1 > vals;
19522025 vals.push_back (genLValExpr (expr));
19532026 return vals;
19542027}
19552028
1956- mlir::Value SolidityToMLIRPass::genRValExpr (mlir::Value val,
1957- mlir::Location loc ) {
2029+ mlir::Value SolidityToMLIRPass::genRValExpr (mlir::Value val, mlir::Location loc,
2030+ std::optional< mlir::Type> resTy ) {
19582031 if (mlir::isa<mlir::sol::PointerType>(val.getType ()))
1959- return b.create <mlir::sol::LoadOp>(loc, val);
2032+ val = b.create <mlir::sol::LoadOp>(loc, val);
2033+ if (resTy)
2034+ return genCast (val, *resTy);
19602035 return val;
19612036}
19622037
19632038mlir::Value SolidityToMLIRPass::genRValExpr (Expression const &expr,
19642039 std::optional<mlir::Type> resTy) {
19652040 mlir::Value lVal = genLValExpr (expr);
19662041 assert (lVal);
1967-
1968- mlir::Value val = genRValExpr (lVal, getLoc (expr));
1969- // Generate cast (optional).
1970- if (resTy)
1971- return genCast (val, *resTy);
1972- return val;
2042+ return genRValExpr (lVal, getLoc (expr), resTy);
19732043}
19742044
19752045mlir::SmallVector<mlir::Value>
1976- SolidityToMLIRPass::genRValExprs (Expression const &expr) {
2046+ SolidityToMLIRPass::genRValExprs (Expression const &expr,
2047+ mlir::TypeRange resTys) {
19772048 mlir::SmallVector<mlir::Value> lVals = genLValExprs (expr);
19782049 assert (!lVals.empty ());
2050+ assert (resTys.empty () || lVals.size () == resTys.size ());
19792051
19802052 mlir::SmallVector<mlir::Value, 2 > rVals;
1981- for (mlir::Value lVal : lVals)
1982- rVals.push_back (genRValExpr (lVal, getLoc (expr)));
2053+ if (resTys.empty ()) {
2054+ for (mlir::Value lVal : lVals)
2055+ rVals.push_back (genRValExpr (lVal, getLoc (expr)));
2056+ } else {
2057+ for (auto [lVal, resTy] : llvm::zip (lVals, resTys))
2058+ rVals.push_back (genRValExpr (lVal, getLoc (expr), resTy));
2059+ }
19832060
19842061 return rVals;
19852062}
@@ -1992,22 +2069,23 @@ void SolidityToMLIRPass::lower(
19922069 VariableDeclarationStatement const &varDeclStmt) {
19932070 mlir::Location loc = getLoc (varDeclStmt);
19942071
2072+ mlir::SmallVector<mlir::Type> varTys;
2073+ for (auto const &varDeclPtr : varDeclStmt.declarations ())
2074+ varTys.push_back (getType (varDeclPtr->type (), /* indirectFn=*/ true ));
2075+
19952076 mlir::SmallVector<mlir::Value> initExprs (varDeclStmt.declarations ().size ());
19962077 if (Expression const *initExpr = varDeclStmt.initialValue ())
1997- initExprs = genRValExprs (*initExpr);
1998-
1999- for (auto [varDeclPtr, initExpr] :
2000- llvm::zip (varDeclStmt.declarations (), initExprs)) {
2001- VariableDeclaration const &varDecl = *varDeclPtr;
2078+ initExprs = genRValExprs (*initExpr, varTys);
20022079
2003- mlir::Type varTy = getType (varDecl.type (), /* indirectFn=*/ true );
2080+ for (auto [varDeclPtr, varTy, initExpr] :
2081+ llvm::zip (varDeclStmt.declarations (), varTys, initExprs)) {
20042082 mlir::Type allocTy = mlir::sol::PointerType::get (
20052083 b.getContext (), varTy, mlir::sol::DataLocation::Stack);
20062084
20072085 auto addr = b.create <mlir::sol::AllocaOp>(loc, allocTy);
2008- trackLocalVarAddr (varDecl , addr);
2086+ trackLocalVarAddr (*varDeclPtr , addr);
20092087 if (initExpr)
2010- b.create <mlir::sol::StoreOp>(loc, genCast ( initExpr, varTy) , addr);
2088+ b.create <mlir::sol::StoreOp>(loc, initExpr, addr);
20112089 else
20122090 genZeroedVal (addr);
20132091 }
@@ -2038,22 +2116,17 @@ void SolidityToMLIRPass::lower(PlaceholderStatement const &placeholder) {
20382116}
20392117
20402118void SolidityToMLIRPass::lower (Return const &ret) {
2041- TypePointers fnResTys;
2119+ mlir::SmallVector<mlir::Type> fnResTys;
20422120 for (ASTPointer<VariableDeclaration> const &retParam :
20432121 ret.annotation ().function ->returnParameters ())
2044- fnResTys.push_back (retParam->type ());
2122+ fnResTys.push_back (getType ( retParam->type () ));
20452123
20462124 Expression const *astExpr = ret.expression ();
2047- if (astExpr) {
2048- mlir::SmallVector<mlir::Value> exprs = genRValExprs (*astExpr);
2049- mlir::SmallVector<mlir::Value> castedExprs;
2050- for (auto [expr, dstTy] : llvm::zip (exprs, fnResTys)) {
2051- castedExprs.push_back (genCast (expr, getType (dstTy)));
2052- }
2053- b.create <mlir::sol::ReturnOp>(getLoc (ret), castedExprs);
2054- } else {
2125+ if (astExpr)
2126+ b.create <mlir::sol::ReturnOp>(getLoc (ret),
2127+ genRValExprs (*astExpr, fnResTys));
2128+ else
20552129 b.create <mlir::sol::ReturnOp>(getLoc (ret));
2056- }
20572130 b.setInsertionPointToStart (b.createBlock (b.getBlock ()->getParent ()));
20582131}
20592132
0 commit comments