| 
15 | 15 | #include "CIRGenModule.h"  | 
16 | 16 | #include "CIRGenValue.h"  | 
17 | 17 | #include "mlir/IR/BuiltinAttributes.h"  | 
 | 18 | +#include "mlir/IR/Value.h"  | 
18 | 19 | #include "clang/AST/Attr.h"  | 
19 | 20 | #include "clang/AST/CharUnits.h"  | 
20 | 21 | #include "clang/AST/Decl.h"  | 
21 | 22 | #include "clang/AST/Expr.h"  | 
22 | 23 | #include "clang/AST/ExprCXX.h"  | 
23 | 24 | #include "clang/CIR/Dialect/IR/CIRDialect.h"  | 
24 | 25 | #include "clang/CIR/MissingFeatures.h"  | 
 | 26 | +#include <optional>  | 
25 | 27 | 
 
  | 
26 | 28 | using namespace clang;  | 
27 | 29 | using namespace clang::CIRGen;  | 
@@ -229,7 +231,7 @@ void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst,  | 
229 | 231 | 
 
  | 
230 | 232 | static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,  | 
231 | 233 |                                       const VarDecl *vd) {  | 
232 |  | -  QualType T = e->getType();  | 
 | 234 | +  QualType t = e->getType();  | 
233 | 235 | 
 
  | 
234 | 236 |   // If it's thread_local, emit a call to its wrapper function instead.  | 
235 | 237 |   assert(!cir::MissingFeatures::opGlobalThreadLocal());  | 
@@ -259,7 +261,7 @@ static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,  | 
259 | 261 |     cgf.cgm.errorNYI(e->getSourceRange(),  | 
260 | 262 |                      "emitGlobalVarDeclLValue: reference type");  | 
261 | 263 |   else  | 
262 |  | -    lv = cgf.makeAddrLValue(addr, T, AlignmentSource::Decl);  | 
 | 264 | +    lv = cgf.makeAddrLValue(addr, t, AlignmentSource::Decl);  | 
263 | 265 |   assert(!cir::MissingFeatures::setObjCGCLValueClass());  | 
264 | 266 |   return lv;  | 
265 | 267 | }  | 
@@ -1259,10 +1261,28 @@ mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc,  | 
1259 | 1261 |   //  cir.ternary(!x, t, f) -> cir.ternary(x, f, t)  | 
1260 | 1262 |   assert(!cir::MissingFeatures::shouldReverseUnaryCondOnBoolExpr());  | 
1261 | 1263 | 
 
  | 
1262 |  | -  if (isa<ConditionalOperator>(cond)) {  | 
1263 |  | -    cgm.errorNYI(cond->getExprLoc(), "Ternary NYI");  | 
1264 |  | -    assert(!cir::MissingFeatures::ternaryOp());  | 
1265 |  | -    return createDummyValue(loc, cond->getType());  | 
 | 1264 | +  if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) {  | 
 | 1265 | +    Expr *trueExpr = condOp->getTrueExpr();  | 
 | 1266 | +    Expr *falseExpr = condOp->getFalseExpr();  | 
 | 1267 | +    mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond());  | 
 | 1268 | + | 
 | 1269 | +    mlir::Value ternaryOpRes =  | 
 | 1270 | +        builder  | 
 | 1271 | +            .create<cir::TernaryOp>(  | 
 | 1272 | +                loc, condV, /*thenBuilder=*/  | 
 | 1273 | +                [this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) {  | 
 | 1274 | +                  mlir::Value lhs = emitScalarExpr(trueExpr);  | 
 | 1275 | +                  b.create<cir::YieldOp>(loc, lhs);  | 
 | 1276 | +                },  | 
 | 1277 | +                /*elseBuilder=*/  | 
 | 1278 | +                [this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) {  | 
 | 1279 | +                  mlir::Value rhs = emitScalarExpr(falseExpr);  | 
 | 1280 | +                  b.create<cir::YieldOp>(loc, rhs);  | 
 | 1281 | +                })  | 
 | 1282 | +            .getResult();  | 
 | 1283 | + | 
 | 1284 | +    return emitScalarConversion(ternaryOpRes, condOp->getType(),  | 
 | 1285 | +                                getContext().BoolTy, condOp->getExprLoc());  | 
1266 | 1286 |   }  | 
1267 | 1287 | 
 
  | 
1268 | 1288 |   if (isa<CXXThrowExpr>(cond)) {  | 
@@ -1394,13 +1414,84 @@ mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,  | 
1394 | 1414 |   return builder.createDummyValue(loc, t, alignment);  | 
1395 | 1415 | }  | 
1396 | 1416 | 
 
  | 
1397 |  | -/// This creates an alloca and inserts it into the entry block if  | 
1398 |  | -/// \p insertIntoFnEntryBlock is true, otherwise it inserts it at the current  | 
1399 |  | -/// insertion point of the builder.  | 
 | 1417 | +//===----------------------------------------------------------------------===//  | 
 | 1418 | +// CIR builder helpers  | 
 | 1419 | +//===----------------------------------------------------------------------===//  | 
 | 1420 | + | 
 | 1421 | +Address CIRGenFunction::createMemTemp(QualType ty, mlir::Location loc,  | 
 | 1422 | +                                      const Twine &name, Address *alloca,  | 
 | 1423 | +                                      mlir::OpBuilder::InsertPoint ip) {  | 
 | 1424 | +  // FIXME: Should we prefer the preferred type alignment here?  | 
 | 1425 | +  return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name,  | 
 | 1426 | +                       alloca, ip);  | 
 | 1427 | +}  | 
 | 1428 | + | 
 | 1429 | +Address CIRGenFunction::createMemTemp(QualType ty, CharUnits align,  | 
 | 1430 | +                                      mlir::Location loc, const Twine &name,  | 
 | 1431 | +                                      Address *alloca,  | 
 | 1432 | +                                      mlir::OpBuilder::InsertPoint ip) {  | 
 | 1433 | +  Address result = createTempAlloca(convertTypeForMem(ty), align, loc, name,  | 
 | 1434 | +                                    /*ArraySize=*/nullptr, alloca, ip);  | 
 | 1435 | +  if (ty->isConstantMatrixType()) {  | 
 | 1436 | +    assert(!cir::MissingFeatures::matrixType());  | 
 | 1437 | +    cgm.errorNYI(loc, "temporary matrix value");  | 
 | 1438 | +  }  | 
 | 1439 | +  return result;  | 
 | 1440 | +}  | 
 | 1441 | + | 
 | 1442 | +/// This creates a alloca and inserts it into the entry block of the  | 
 | 1443 | +/// current region.  | 
 | 1444 | +Address CIRGenFunction::createTempAllocaWithoutCast(  | 
 | 1445 | +    mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name,  | 
 | 1446 | +    mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) {  | 
 | 1447 | +  cir::AllocaOp alloca = ip.isSet()  | 
 | 1448 | +                             ? createTempAlloca(ty, loc, name, ip, arraySize)  | 
 | 1449 | +                             : createTempAlloca(ty, loc, name, arraySize);  | 
 | 1450 | +  alloca.setAlignmentAttr(cgm.getSize(align));  | 
 | 1451 | +  return Address(alloca, ty, align);  | 
 | 1452 | +}  | 
 | 1453 | + | 
 | 1454 | +/// This creates a alloca and inserts it into the entry block. The alloca is  | 
 | 1455 | +/// casted to default address space if necessary.  | 
1400 | 1456 | Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,  | 
1401 | 1457 |                                          mlir::Location loc, const Twine &name,  | 
1402 |  | -                                         bool insertIntoFnEntryBlock) {  | 
1403 |  | -  mlir::Value alloca =  | 
1404 |  | -      emitAlloca(name.str(), ty, loc, align, insertIntoFnEntryBlock);  | 
1405 |  | -  return Address(alloca, ty, align);  | 
 | 1458 | +                                         mlir::Value arraySize,  | 
 | 1459 | +                                         Address *allocaAddr,  | 
 | 1460 | +                                         mlir::OpBuilder::InsertPoint ip) {  | 
 | 1461 | +  Address alloca =  | 
 | 1462 | +      createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip);  | 
 | 1463 | +  if (allocaAddr)  | 
 | 1464 | +    *allocaAddr = alloca;  | 
 | 1465 | +  mlir::Value v = alloca.getPointer();  | 
 | 1466 | +  // Alloca always returns a pointer in alloca address space, which may  | 
 | 1467 | +  // be different from the type defined by the language. For example,  | 
 | 1468 | +  // in C++ the auto variables are in the default address space. Therefore  | 
 | 1469 | +  // cast alloca to the default address space when necessary.  | 
 | 1470 | +  assert(!cir::MissingFeatures::addressSpace());  | 
 | 1471 | +  return Address(v, ty, align);  | 
 | 1472 | +}  | 
 | 1473 | + | 
 | 1474 | +/// This creates an alloca and inserts it into the entry block if \p ArraySize  | 
 | 1475 | +/// is nullptr, otherwise inserts it at the current insertion point of the  | 
 | 1476 | +/// builder.  | 
 | 1477 | +cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,  | 
 | 1478 | +                                               mlir::Location loc,  | 
 | 1479 | +                                               const Twine &name,  | 
 | 1480 | +                                               mlir::Value arraySize,  | 
 | 1481 | +                                               bool insertIntoFnEntryBlock) {  | 
 | 1482 | +  return cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),  | 
 | 1483 | +                                        insertIntoFnEntryBlock, arraySize)  | 
 | 1484 | +                                 .getDefiningOp());  | 
 | 1485 | +}  | 
 | 1486 | + | 
 | 1487 | +/// This creates an alloca and inserts it into the provided insertion point  | 
 | 1488 | +cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,  | 
 | 1489 | +                                               mlir::Location loc,  | 
 | 1490 | +                                               const Twine &name,  | 
 | 1491 | +                                               mlir::OpBuilder::InsertPoint ip,  | 
 | 1492 | +                                               mlir::Value arraySize) {  | 
 | 1493 | +  assert(ip.isSet() && "Insertion point is not set");  | 
 | 1494 | +  return cast<cir::AllocaOp>(  | 
 | 1495 | +      emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)  | 
 | 1496 | +          .getDefiningOp());  | 
1406 | 1497 | }  | 
0 commit comments