|
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
13 | 13 | #include "Address.h" |
| 14 | +#include "CIRGenConstantEmitter.h" |
14 | 15 | #include "CIRGenFunction.h" |
15 | 16 | #include "CIRGenModule.h" |
16 | 17 | #include "CIRGenValue.h" |
@@ -1495,3 +1496,57 @@ cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty, |
1495 | 1496 | emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize) |
1496 | 1497 | .getDefiningOp()); |
1497 | 1498 | } |
| 1499 | + |
| 1500 | +/// Try to emit a reference to the given value without producing it as |
| 1501 | +/// an l-value. For many cases, this is just an optimization, but it avoids |
| 1502 | +/// us needing to emit global copies of variables if they're named without |
| 1503 | +/// triggering a formal use in a context where we can't emit a direct |
| 1504 | +/// reference to them, for instance if a block or lambda or a member of a |
| 1505 | +/// local class uses a const int variable or constexpr variable from an |
| 1506 | +/// enclosing function. |
| 1507 | +/// |
| 1508 | +/// For named members of enums, this is the only way they are emitted. |
| 1509 | +CIRGenFunction::ConstantEmission |
| 1510 | +CIRGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { |
| 1511 | + ValueDecl *value = refExpr->getDecl(); |
| 1512 | + |
| 1513 | + // There is a lot more to do here, but for now only EnumConstantDecl is |
| 1514 | + // supported. |
| 1515 | + assert(!cir::MissingFeatures::tryEmitAsConstant()); |
| 1516 | + |
| 1517 | + // The value needs to be an enum constant or a constant variable. |
| 1518 | + if (!isa<EnumConstantDecl>(value)) |
| 1519 | + return ConstantEmission(); |
| 1520 | + |
| 1521 | + Expr::EvalResult result; |
| 1522 | + if (!refExpr->EvaluateAsRValue(result, getContext())) |
| 1523 | + return ConstantEmission(); |
| 1524 | + |
| 1525 | + QualType resultType = refExpr->getType(); |
| 1526 | + |
| 1527 | + // As long as we're only handling EnumConstantDecl, there should be no |
| 1528 | + // side-effects. |
| 1529 | + assert(!result.HasSideEffects); |
| 1530 | + |
| 1531 | + // Emit as a constant. |
| 1532 | + // FIXME(cir): have emitAbstract build a TypedAttr instead (this requires |
| 1533 | + // somewhat heavy refactoring...) |
| 1534 | + mlir::Attribute c = ConstantEmitter(*this).emitAbstract( |
| 1535 | + refExpr->getLocation(), result.Val, resultType); |
| 1536 | + mlir::TypedAttr cstToEmit = mlir::dyn_cast_if_present<mlir::TypedAttr>(c); |
| 1537 | + assert(cstToEmit && "expected a typed attribute"); |
| 1538 | + |
| 1539 | + assert(!cir::MissingFeatures::generateDebugInfo()); |
| 1540 | + |
| 1541 | + return ConstantEmission::forValue(cstToEmit); |
| 1542 | +} |
| 1543 | + |
| 1544 | +mlir::Value CIRGenFunction::emitScalarConstant( |
| 1545 | + const CIRGenFunction::ConstantEmission &constant, Expr *e) { |
| 1546 | + assert(constant && "not a constant"); |
| 1547 | + if (constant.isReference()) { |
| 1548 | + cgm.errorNYI(e->getSourceRange(), "emitScalarConstant: reference"); |
| 1549 | + return {}; |
| 1550 | + } |
| 1551 | + return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue()); |
| 1552 | +} |
0 commit comments