Skip to content

Commit cde2287

Browse files
committed
Merge remote-tracking branch 'refs/remotes/upstream/main' into add-ref-map
2 parents ac8e562 + 23022a4 commit cde2287

File tree

69 files changed

+2746
-435
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2746
-435
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,9 @@ def CIR_ConstantOp : CIR_Op<"const", [
291291
return ptrAttr.isNullValue();
292292
return false;
293293
}
294+
295+
template <typename T>
296+
T getValueAttr() { return mlir::dyn_cast<T>(getValue()); }
294297
}];
295298

296299
let hasFolder = 1;

clang/include/clang/CIR/Dialect/IR/CIRTypes.td

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,35 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
281281
}];
282282
}
283283

284+
//===----------------------------------------------------------------------===//
285+
// CIR_VPtrType
286+
//===----------------------------------------------------------------------===//
287+
288+
def CIR_VPtrType : CIR_Type<"VPtr", "vptr", [
289+
DeclareTypeInterfaceMethods<DataLayoutTypeInterface>
290+
]> {
291+
let summary = "CIR type that is used for the vptr member of C++ objects";
292+
let description = [{
293+
`cir.vptr` is a special type used as the type for the vptr member of a C++
294+
object. This avoids using arbitrary pointer types to declare vptr values
295+
and allows stronger type-based checking for operations that use or provide
296+
access to the vptr.
297+
298+
This type will be the element type of the 'vptr' member of structures that
299+
require a vtable pointer. A pointer to this type is returned by the
300+
`cir.vtable.address_point` and `cir.vtable.get_vptr` operations, and this
301+
pointer may be passed to the `cir.vtable.get_virtual_fn_addr` operation to
302+
get the address of a virtual function pointer.
303+
304+
The pointer may also be cast to other pointer types in order to perform
305+
pointer arithmetic based on information encoded in the AST layout to get
306+
the offset from a pointer to a dynamic object to the base object pointer,
307+
the base object offset value from the vtable, or the type information
308+
entry for an object.
309+
TODO: We should have special operations to do that too.
310+
}];
311+
}
312+
284313
//===----------------------------------------------------------------------===//
285314
// BoolType
286315
//===----------------------------------------------------------------------===//
@@ -635,7 +664,7 @@ def CIRRecordType : Type<
635664
def CIR_AnyType : AnyTypeOf<[
636665
CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_IntType,
637666
CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_RecordType,
638-
CIR_ComplexType
667+
CIR_ComplexType, CIR_VPtrType
639668
]>;
640669

641670
#endif // CLANG_CIR_DIALECT_IR_CIRTYPES_TD

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ struct MissingFeatures {
223223
static bool lowerAggregateLoadStore() { return false; }
224224
static bool lowerModeOptLevel() { return false; }
225225
static bool maybeHandleStaticInExternC() { return false; }
226+
static bool mergeAllConstants() { return false; }
226227
static bool metaDataNode() { return false; }
227228
static bool moduleNameHash() { return false; }
228229
static bool msabi() { return false; }

clang/lib/CIR/CodeGen/Address.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@ class Address {
101101
}
102102

103103
clang::CharUnits getAlignment() const { return alignment; }
104+
105+
/// Get the operation which defines this address.
106+
mlir::Operation *getDefiningOp() const {
107+
if (!isValid())
108+
return nullptr;
109+
return getPointer().getDefiningOp();
110+
}
111+
112+
template <typename OpTy> OpTy getDefiningOp() const {
113+
return mlir::dyn_cast_or_null<OpTy>(getDefiningOp());
114+
}
104115
};
105116

106117
} // namespace clang::CIRGen

clang/lib/CIR/CodeGen/CIRGenClass.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,16 @@ void CIRGenFunction::emitCXXAggrConstructorCall(
349349
// doesn't happen, but it's not clear that it's worth it.
350350

351351
// Optimize for a constant count.
352-
auto constantCount = dyn_cast<cir::ConstantOp>(numElements.getDefiningOp());
353-
if (constantCount) {
354-
auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
355-
// Just skip out if the constant count is zero.
356-
if (constIntAttr && constIntAttr.getUInt() == 0)
357-
return;
352+
if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
353+
if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>()) {
354+
// Just skip out if the constant count is zero.
355+
if (constIntAttr.getUInt() == 0)
356+
return;
357+
// Otherwise, emit the check.
358+
}
359+
360+
if (constantCount.use_empty())
361+
constantCount.erase();
358362
} else {
359363
// Otherwise, emit the check.
360364
cgm.errorNYI(e->getSourceRange(), "dynamic-length array expression");
@@ -417,9 +421,6 @@ void CIRGenFunction::emitCXXAggrConstructorCall(
417421
builder.create<cir::YieldOp>(loc);
418422
});
419423
}
420-
421-
if (constantCount.use_empty())
422-
constantCount.erase();
423424
}
424425

425426
void CIRGenFunction::emitDelegateCXXConstructorCall(

clang/lib/CIR/CodeGen/CIRGenDecl.cpp

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,27 @@ void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
653653
assert(!cir::MissingFeatures::sanitizers());
654654
}
655655

656+
namespace {
657+
struct DestroyObject final : EHScopeStack::Cleanup {
658+
DestroyObject(Address addr, QualType type,
659+
CIRGenFunction::Destroyer *destroyer)
660+
: addr(addr), type(type), destroyer(destroyer) {}
661+
662+
Address addr;
663+
QualType type;
664+
CIRGenFunction::Destroyer *destroyer;
665+
666+
void emit(CIRGenFunction &cgf) override {
667+
cgf.emitDestroy(addr, type, destroyer);
668+
}
669+
};
670+
} // namespace
671+
672+
void CIRGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr,
673+
QualType type, Destroyer *destroyer) {
674+
pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
675+
}
676+
656677
/// Destroys all the elements of the given array, beginning from last to first.
657678
/// The array cannot be zero-length.
658679
///
@@ -740,22 +761,6 @@ CIRGenFunction::getDestroyer(QualType::DestructionKind kind) {
740761
llvm_unreachable("Unknown DestructionKind");
741762
}
742763

743-
namespace {
744-
struct DestroyObject final : EHScopeStack::Cleanup {
745-
DestroyObject(Address addr, QualType type,
746-
CIRGenFunction::Destroyer *destroyer)
747-
: addr(addr), type(type), destroyer(destroyer) {}
748-
749-
Address addr;
750-
QualType type;
751-
CIRGenFunction::Destroyer *destroyer;
752-
753-
void emit(CIRGenFunction &cgf) override {
754-
cgf.emitDestroy(addr, type, destroyer);
755-
}
756-
};
757-
} // namespace
758-
759764
/// Enter a destroy cleanup for the given local variable.
760765
void CIRGenFunction::emitAutoVarTypeCleanup(
761766
const CIRGenFunction::AutoVarEmission &emission,

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 148 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -721,17 +721,16 @@ static const Expr *getSimpleArrayDecayOperand(const Expr *e) {
721721

722722
static cir::IntAttr getConstantIndexOrNull(mlir::Value idx) {
723723
// TODO(cir): should we consider using MLIRs IndexType instead of IntegerAttr?
724-
if (auto constantOp = dyn_cast<cir::ConstantOp>(idx.getDefiningOp()))
725-
return mlir::dyn_cast<cir::IntAttr>(constantOp.getValue());
724+
if (auto constantOp = idx.getDefiningOp<cir::ConstantOp>())
725+
return constantOp.getValueAttr<cir::IntAttr>();
726726
return {};
727727
}
728728

729729
static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx,
730730
CharUnits eltSize) {
731731
// If we have a constant index, we can use the exact offset of the
732732
// element we're accessing.
733-
const cir::IntAttr constantIdx = getConstantIndexOrNull(idx);
734-
if (constantIdx) {
733+
if (const cir::IntAttr constantIdx = getConstantIndexOrNull(idx)) {
735734
const CharUnits offset = constantIdx.getValue().getZExtValue() * eltSize;
736735
return arrayAlign.alignmentAtOffset(offset);
737736
}
@@ -1105,6 +1104,151 @@ void CIRGenFunction::emitAnyExprToMem(const Expr *e, Address location,
11051104
llvm_unreachable("bad evaluation kind");
11061105
}
11071106

1107+
static Address createReferenceTemporary(CIRGenFunction &cgf,
1108+
const MaterializeTemporaryExpr *m,
1109+
const Expr *inner) {
1110+
// TODO(cir): cgf.getTargetHooks();
1111+
switch (m->getStorageDuration()) {
1112+
case SD_FullExpression:
1113+
case SD_Automatic: {
1114+
QualType ty = inner->getType();
1115+
1116+
assert(!cir::MissingFeatures::mergeAllConstants());
1117+
1118+
// The temporary memory should be created in the same scope as the extending
1119+
// declaration of the temporary materialization expression.
1120+
cir::AllocaOp extDeclAlloca;
1121+
if (const ValueDecl *extDecl = m->getExtendingDecl()) {
1122+
auto extDeclAddrIter = cgf.localDeclMap.find(extDecl);
1123+
if (extDeclAddrIter != cgf.localDeclMap.end())
1124+
extDeclAlloca = extDeclAddrIter->second.getDefiningOp<cir::AllocaOp>();
1125+
}
1126+
mlir::OpBuilder::InsertPoint ip;
1127+
if (extDeclAlloca)
1128+
ip = {extDeclAlloca->getBlock(), extDeclAlloca->getIterator()};
1129+
return cgf.createMemTemp(ty, cgf.getLoc(m->getSourceRange()),
1130+
cgf.getCounterRefTmpAsString(), /*alloca=*/nullptr,
1131+
ip);
1132+
}
1133+
case SD_Thread:
1134+
case SD_Static: {
1135+
cgf.cgm.errorNYI(
1136+
m->getSourceRange(),
1137+
"createReferenceTemporary: static/thread storage duration");
1138+
return Address::invalid();
1139+
}
1140+
1141+
case SD_Dynamic:
1142+
llvm_unreachable("temporary can't have dynamic storage duration");
1143+
}
1144+
llvm_unreachable("unknown storage duration");
1145+
}
1146+
1147+
static void pushTemporaryCleanup(CIRGenFunction &cgf,
1148+
const MaterializeTemporaryExpr *m,
1149+
const Expr *e, Address referenceTemporary) {
1150+
// Objective-C++ ARC:
1151+
// If we are binding a reference to a temporary that has ownership, we
1152+
// need to perform retain/release operations on the temporary.
1153+
//
1154+
// FIXME(ogcg): This should be looking at e, not m.
1155+
if (m->getType().getObjCLifetime()) {
1156+
cgf.cgm.errorNYI(e->getSourceRange(), "pushTemporaryCleanup: ObjCLifetime");
1157+
return;
1158+
}
1159+
1160+
CXXDestructorDecl *referenceTemporaryDtor = nullptr;
1161+
if (const clang::RecordType *rt = e->getType()
1162+
->getBaseElementTypeUnsafe()
1163+
->getAs<clang::RecordType>()) {
1164+
// Get the destructor for the reference temporary.
1165+
auto *classDecl = cast<CXXRecordDecl>(rt->getDecl());
1166+
if (!classDecl->hasTrivialDestructor())
1167+
referenceTemporaryDtor = classDecl->getDestructor();
1168+
}
1169+
1170+
if (!referenceTemporaryDtor)
1171+
return;
1172+
1173+
// Call the destructor for the temporary.
1174+
switch (m->getStorageDuration()) {
1175+
case SD_Static:
1176+
case SD_Thread:
1177+
cgf.cgm.errorNYI(e->getSourceRange(),
1178+
"pushTemporaryCleanup: static/thread storage duration");
1179+
return;
1180+
1181+
case SD_FullExpression:
1182+
cgf.pushDestroy(NormalAndEHCleanup, referenceTemporary, e->getType(),
1183+
CIRGenFunction::destroyCXXObject);
1184+
break;
1185+
1186+
case SD_Automatic:
1187+
cgf.cgm.errorNYI(e->getSourceRange(),
1188+
"pushTemporaryCleanup: automatic storage duration");
1189+
break;
1190+
1191+
case SD_Dynamic:
1192+
llvm_unreachable("temporary cannot have dynamic storage duration");
1193+
}
1194+
}
1195+
1196+
LValue CIRGenFunction::emitMaterializeTemporaryExpr(
1197+
const MaterializeTemporaryExpr *m) {
1198+
const Expr *e = m->getSubExpr();
1199+
1200+
assert((!m->getExtendingDecl() || !isa<VarDecl>(m->getExtendingDecl()) ||
1201+
!cast<VarDecl>(m->getExtendingDecl())->isARCPseudoStrong()) &&
1202+
"Reference should never be pseudo-strong!");
1203+
1204+
// FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so
1205+
// as that will cause the lifetime adjustment to be lost for ARC
1206+
auto ownership = m->getType().getObjCLifetime();
1207+
if (ownership != Qualifiers::OCL_None &&
1208+
ownership != Qualifiers::OCL_ExplicitNone) {
1209+
cgm.errorNYI(e->getSourceRange(),
1210+
"emitMaterializeTemporaryExpr: ObjCLifetime");
1211+
return {};
1212+
}
1213+
1214+
SmallVector<const Expr *, 2> commaLHSs;
1215+
SmallVector<SubobjectAdjustment, 2> adjustments;
1216+
e = e->skipRValueSubobjectAdjustments(commaLHSs, adjustments);
1217+
1218+
for (const Expr *ignored : commaLHSs)
1219+
emitIgnoredExpr(ignored);
1220+
1221+
if (isa<OpaqueValueExpr>(e)) {
1222+
cgm.errorNYI(e->getSourceRange(),
1223+
"emitMaterializeTemporaryExpr: OpaqueValueExpr");
1224+
return {};
1225+
}
1226+
1227+
// Create and initialize the reference temporary.
1228+
Address object = createReferenceTemporary(*this, m, e);
1229+
1230+
if (auto var = object.getPointer().getDefiningOp<cir::GlobalOp>()) {
1231+
// TODO(cir): add something akin to stripPointerCasts() to ptr above
1232+
cgm.errorNYI(e->getSourceRange(), "emitMaterializeTemporaryExpr: GlobalOp");
1233+
return {};
1234+
} else {
1235+
assert(!cir::MissingFeatures::emitLifetimeMarkers());
1236+
emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
1237+
}
1238+
pushTemporaryCleanup(*this, m, e, object);
1239+
1240+
// Perform derived-to-base casts and/or field accesses, to get from the
1241+
// temporary object we created (and, potentially, for which we extended
1242+
// the lifetime) to the subobject we're binding the reference to.
1243+
if (!adjustments.empty()) {
1244+
cgm.errorNYI(e->getSourceRange(),
1245+
"emitMaterializeTemporaryExpr: Adjustments");
1246+
return {};
1247+
}
1248+
1249+
return makeAddrLValue(object, m->getType(), AlignmentSource::Decl);
1250+
}
1251+
11081252
LValue CIRGenFunction::emitCompoundLiteralLValue(const CompoundLiteralExpr *e) {
11091253
if (e->isFileScope()) {
11101254
cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ struct BinOpInfo {
4848
/// Check if the binop can result in integer overflow.
4949
bool mayHaveIntegerOverflow() const {
5050
// Without constant input, we can't rule out overflow.
51-
auto lhsci = dyn_cast<cir::ConstantOp>(lhs.getDefiningOp());
52-
auto rhsci = dyn_cast<cir::ConstantOp>(rhs.getDefiningOp());
51+
auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
52+
auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
5353
if (!lhsci || !rhsci)
5454
return true;
5555

@@ -626,6 +626,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
626626

627627
mlir::Value VisitCXXThisExpr(CXXThisExpr *te) { return cgf.loadCXXThis(); }
628628

629+
mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
629630
mlir::Value VisitCXXNewExpr(const CXXNewExpr *e) {
630631
return cgf.emitCXXNewExpr(e);
631632
}
@@ -1217,6 +1218,29 @@ mlir::Value ScalarExprEmitter::emitCompoundAssign(
12171218
return emitLoadOfLValue(lhs, e->getExprLoc());
12181219
}
12191220

1221+
mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1222+
mlir::Location scopeLoc = cgf.getLoc(e->getSourceRange());
1223+
mlir::OpBuilder &builder = cgf.builder;
1224+
1225+
auto scope = cir::ScopeOp::create(
1226+
builder, scopeLoc,
1227+
/*scopeBuilder=*/
1228+
[&](mlir::OpBuilder &b, mlir::Type &yieldTy, mlir::Location loc) {
1229+
CIRGenFunction::LexicalScope lexScope{cgf, loc,
1230+
builder.getInsertionBlock()};
1231+
mlir::Value scopeYieldVal = Visit(e->getSubExpr());
1232+
if (scopeYieldVal) {
1233+
// Defend against dominance problems caused by jumps out of expression
1234+
// evaluation through the shared cleanup block.
1235+
lexScope.forceCleanup();
1236+
cir::YieldOp::create(builder, loc, scopeYieldVal);
1237+
yieldTy = scopeYieldVal.getType();
1238+
}
1239+
});
1240+
1241+
return scope.getNumResults() > 0 ? scope->getResult(0) : nullptr;
1242+
}
1243+
12201244
} // namespace
12211245

12221246
LValue

0 commit comments

Comments
 (0)