|
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