Skip to content

Commit 782e37d

Browse files
committed
Merge branch 'main' of https://github.com/llvm/llvm-project into fix_variable_names
2 parents 9d30d62 + 761be78 commit 782e37d

File tree

8 files changed

+310
-51
lines changed

8 files changed

+310
-51
lines changed

clang/lib/CIR/CodeGen/CIRGenClass.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,109 @@ void CIRGenFunction::destroyCXXObject(CIRGenFunction &cgf, Address addr,
870870
/*delegating=*/false, addr, type);
871871
}
872872

873+
namespace {
874+
class DestroyField final : public EHScopeStack::Cleanup {
875+
const FieldDecl *field;
876+
CIRGenFunction::Destroyer *destroyer;
877+
878+
public:
879+
DestroyField(const FieldDecl *field, CIRGenFunction::Destroyer *destroyer)
880+
: field(field), destroyer(destroyer) {}
881+
882+
void emit(CIRGenFunction &cgf) override {
883+
// Find the address of the field.
884+
Address thisValue = cgf.loadCXXThisAddress();
885+
CanQualType recordTy =
886+
cgf.getContext().getCanonicalTagType(field->getParent());
887+
LValue thisLV = cgf.makeAddrLValue(thisValue, recordTy);
888+
LValue lv = cgf.emitLValueForField(thisLV, field);
889+
assert(lv.isSimple());
890+
891+
assert(!cir::MissingFeatures::ehCleanupFlags());
892+
cgf.emitDestroy(lv.getAddress(), field->getType(), destroyer);
893+
}
894+
895+
// This is a placeholder until EHCleanupScope is implemented.
896+
size_t getSize() const override {
897+
assert(!cir::MissingFeatures::ehCleanupScope());
898+
return sizeof(DestroyField);
899+
}
900+
};
901+
} // namespace
902+
903+
/// Emit all code that comes at the end of class's destructor. This is to call
904+
/// destructors on members and base classes in reverse order of their
905+
/// construction.
906+
///
907+
/// For a deleting destructor, this also handles the case where a destroying
908+
/// operator delete completely overrides the definition.
909+
void CIRGenFunction::enterDtorCleanups(const CXXDestructorDecl *dd,
910+
CXXDtorType dtorType) {
911+
assert((!dd->isTrivial() || dd->hasAttr<DLLExportAttr>()) &&
912+
"Should not emit dtor epilogue for non-exported trivial dtor!");
913+
914+
// The deleting-destructor phase just needs to call the appropriate
915+
// operator delete that Sema picked up.
916+
if (dtorType == Dtor_Deleting) {
917+
cgm.errorNYI(dd->getSourceRange(), "deleting destructor cleanups");
918+
return;
919+
}
920+
921+
const CXXRecordDecl *classDecl = dd->getParent();
922+
923+
// Unions have no bases and do not call field destructors.
924+
if (classDecl->isUnion())
925+
return;
926+
927+
// The complete-destructor phase just destructs all the virtual bases.
928+
if (dtorType == Dtor_Complete) {
929+
assert(!cir::MissingFeatures::sanitizers());
930+
931+
if (classDecl->getNumVBases())
932+
cgm.errorNYI(dd->getSourceRange(), "virtual base destructor cleanups");
933+
934+
return;
935+
}
936+
937+
assert(dtorType == Dtor_Base);
938+
assert(!cir::MissingFeatures::sanitizers());
939+
940+
// Destroy non-virtual bases.
941+
for (const CXXBaseSpecifier &base : classDecl->bases()) {
942+
// Ignore virtual bases.
943+
if (base.isVirtual())
944+
continue;
945+
946+
CXXRecordDecl *baseClassDecl = base.getType()->getAsCXXRecordDecl();
947+
948+
if (baseClassDecl->hasTrivialDestructor())
949+
assert(!cir::MissingFeatures::sanitizers());
950+
else
951+
cgm.errorNYI(dd->getSourceRange(),
952+
"non-trivial base destructor cleanups");
953+
}
954+
955+
assert(!cir::MissingFeatures::sanitizers());
956+
957+
// Destroy direct fields.
958+
for (const FieldDecl *field : classDecl->fields()) {
959+
QualType type = field->getType();
960+
QualType::DestructionKind dtorKind = type.isDestructedType();
961+
if (!dtorKind)
962+
continue;
963+
964+
// Anonymous union members do not have their destructors called.
965+
const RecordType *rt = type->getAsUnionType();
966+
if (rt && rt->getOriginalDecl()->isAnonymousStructOrUnion())
967+
continue;
968+
969+
CleanupKind cleanupKind = getCleanupKind(dtorKind);
970+
assert(!cir::MissingFeatures::ehCleanupFlags());
971+
ehStack.pushCleanup<DestroyField>(cleanupKind, field,
972+
getDestroyer(dtorKind));
973+
}
974+
}
975+
873976
void CIRGenFunction::emitDelegatingCXXConstructorCall(
874977
const CXXConstructorDecl *ctor, const FunctionArgList &args) {
875978
assert(ctor->isDelegatingConstructor());

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,9 @@ void CIRGenFunction::emitDestructorBody(FunctionArgList &args) {
689689
cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
690690

691691
assert(!cir::MissingFeatures::sanitizers());
692-
assert(!cir::MissingFeatures::dtorCleanups());
692+
693+
// Enter the epilogue cleanups.
694+
RunCleanupsScope dtorEpilogue(*this);
693695

694696
// If this is the complete variant, just invoke the base variant;
695697
// the epilogue will destruct the virtual bases. But we can't do
@@ -708,7 +710,8 @@ void CIRGenFunction::emitDestructorBody(FunctionArgList &args) {
708710
assert((body || getTarget().getCXXABI().isMicrosoft()) &&
709711
"can't emit a dtor without a body for non-Microsoft ABIs");
710712

711-
assert(!cir::MissingFeatures::dtorCleanups());
713+
// Enter the cleanup scopes for virtual bases.
714+
enterDtorCleanups(dtor, Dtor_Complete);
712715

713716
if (!isTryBody) {
714717
QualType thisTy = dtor->getFunctionObjectParameterType();
@@ -723,7 +726,9 @@ void CIRGenFunction::emitDestructorBody(FunctionArgList &args) {
723726
case Dtor_Base:
724727
assert(body);
725728

726-
assert(!cir::MissingFeatures::dtorCleanups());
729+
// Enter the cleanup scopes for fields and non-virtual bases.
730+
enterDtorCleanups(dtor, Dtor_Base);
731+
727732
assert(!cir::MissingFeatures::vtableInitialization());
728733

729734
if (isTryBody) {
@@ -741,7 +746,8 @@ void CIRGenFunction::emitDestructorBody(FunctionArgList &args) {
741746
break;
742747
}
743748

744-
assert(!cir::MissingFeatures::dtorCleanups());
749+
// Jump out through the epilogue cleanups.
750+
dtorEpilogue.forceCleanup();
745751

746752
// Exit the try if applicable.
747753
if (isTryBody)

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,33 @@ class CIRGenFunction : public CIRGenTypeCache {
556556
cir::GlobalOp gv,
557557
cir::GetGlobalOp gvAddr);
558558

559+
/// Enter the cleanups necessary to complete the given phase of destruction
560+
/// for a destructor. The end result should call destructors on members and
561+
/// base classes in reverse order of their construction.
562+
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type);
563+
564+
/// Determines whether an EH cleanup is required to destroy a type
565+
/// with the given destruction kind.
566+
/// TODO(cir): could be shared with Clang LLVM codegen
567+
bool needsEHCleanup(QualType::DestructionKind kind) {
568+
switch (kind) {
569+
case QualType::DK_none:
570+
return false;
571+
case QualType::DK_cxx_destructor:
572+
case QualType::DK_objc_weak_lifetime:
573+
case QualType::DK_nontrivial_c_struct:
574+
return getLangOpts().Exceptions;
575+
case QualType::DK_objc_strong_lifetime:
576+
return getLangOpts().Exceptions &&
577+
cgm.getCodeGenOpts().ObjCAutoRefCountExceptions;
578+
}
579+
llvm_unreachable("bad destruction kind");
580+
}
581+
582+
CleanupKind getCleanupKind(QualType::DestructionKind kind) {
583+
return needsEHCleanup(kind) ? NormalAndEHCleanup : NormalCleanup;
584+
}
585+
559586
/// Set the address of a local variable.
560587
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr) {
561588
assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");

clang/test/CIR/CodeGen/dtors.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,40 @@ bool test_temp_and() { return make_temp(1) && make_temp(2); }
171171
// OGCG: br label %[[CLEANUP_DONE]]
172172
// OGCG: [[CLEANUP_DONE]]:
173173
// OGCG: call void @_ZN1BD2Ev(ptr {{.*}} %[[REF_TMP0]])
174+
175+
struct C {
176+
~C();
177+
};
178+
179+
struct D {
180+
int n;
181+
C c;
182+
~D() {}
183+
};
184+
185+
// CIR: cir.func {{.*}} @_ZN1DD2Ev
186+
// CIR: %[[C:.*]] = cir.get_member %{{.*}}[1] {name = "c"}
187+
// CIR: cir.call @_ZN1CD1Ev(%[[C]])
188+
189+
// LLVM: define {{.*}} void @_ZN1DD2Ev
190+
// LLVM: %[[C:.*]] = getelementptr %struct.D, ptr %{{.*}}, i32 0, i32 1
191+
// LLVM: call void @_ZN1CD1Ev(ptr %[[C]])
192+
193+
// This destructor is defined after the calling function in OGCG.
194+
195+
void test_nested_dtor() {
196+
D d;
197+
}
198+
199+
// CIR: cir.func{{.*}} @_Z16test_nested_dtorv()
200+
// CIR: cir.call @_ZN1DD2Ev(%{{.*}})
201+
202+
// LLVM: define {{.*}} void @_Z16test_nested_dtorv()
203+
// LLVM: call void @_ZN1DD2Ev(ptr %{{.*}})
204+
205+
// OGCG: define {{.*}} void @_Z16test_nested_dtorv()
206+
// OGCG: call void @_ZN1DD2Ev(ptr {{.*}} %{{.*}})
207+
208+
// OGCG: define {{.*}} void @_ZN1DD2Ev
209+
// OGCG: %[[C:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 4
210+
// OGCG: call void @_ZN1CD1Ev(ptr {{.*}} %[[C]])

llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1507,7 +1507,7 @@ void DXILBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
15071507
SmallVectorImpl<uint64_t> &Record,
15081508
unsigned Abbrev) {
15091509
Record.push_back(N->isDistinct());
1510-
Record.push_back(N->getSourceLanguage());
1510+
Record.push_back(N->getSourceLanguage().getUnversionedName());
15111511
Record.push_back(VE.getMetadataOrNullID(N->getFile()));
15121512
Record.push_back(VE.getMetadataOrNullID(N->getRawProducer()));
15131513
Record.push_back(N->isOptimized());

llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,6 +1445,49 @@ def : Pat<(v16i8 (wasm_narrow_u (v8i16 V128:$left), (v8i16 V128:$right))),
14451445
def : Pat<(v8i16 (wasm_narrow_u (v4i32 V128:$left), (v4i32 V128:$right))),
14461446
(NARROW_U_I16x8 $left, $right)>;
14471447

1448+
// Recognize a saturating truncation and convert into the corresponding
1449+
// narrow_TYPE_s or narrow_TYPE_u instruction.
1450+
multiclass SignedSaturatingTruncate<ValueType input, ValueType output,
1451+
Instruction narrow, int minval,
1452+
int maxval, int mask> {
1453+
def : Pat<
1454+
(output (wasm_narrow_u
1455+
(and (smin (smax (input V128:$a), (splat_vector (i32 minval))),
1456+
(splat_vector (i32 maxval))), (splat_vector (i32 mask))),
1457+
(and (smin (smax (input V128:$b), (splat_vector (i32 minval))),
1458+
(splat_vector (i32 maxval))), (splat_vector (i32 mask)))
1459+
)),
1460+
(narrow V128:$a, V128:$b)
1461+
>;
1462+
1463+
def : Pat<
1464+
(output (wasm_narrow_u
1465+
(and (smax (smin (input V128:$a), (splat_vector (i32 maxval))),
1466+
(splat_vector (i32 minval))), (splat_vector (i32 mask))),
1467+
(and (smax (smin (input V128:$b), (splat_vector (i32 maxval))),
1468+
(splat_vector (i32 minval))), (splat_vector (i32 mask)))
1469+
)),
1470+
(narrow V128:$a, V128:$b)
1471+
>;
1472+
}
1473+
1474+
defm : SignedSaturatingTruncate<v8i16, v16i8, NARROW_S_I8x16, -128, 127, 0xFF>;
1475+
defm : SignedSaturatingTruncate<v4i32, v8i16, NARROW_S_I16x8, -32768, 32767, 0xFFFF>;
1476+
1477+
multiclass UnsignedSaturatingTruncate<ValueType input, ValueType output,
1478+
Instruction narrow, int maxval> {
1479+
def : Pat<
1480+
(output (wasm_narrow_u
1481+
(umin (input V128:$a), (splat_vector (i32 maxval))),
1482+
(umin (input V128:$b), (splat_vector (i32 maxval)))
1483+
)),
1484+
(narrow V128:$a, V128:$b)
1485+
>;
1486+
}
1487+
1488+
defm : UnsignedSaturatingTruncate<v8i16, v16i8, NARROW_U_I8x16, 0xFF>;
1489+
defm : UnsignedSaturatingTruncate<v4i32, v8i16, NARROW_U_I16x8, 0xFFFF>;
1490+
14481491
// Bitcasts are nops
14491492
// Matching bitcast t1 to t1 causes strange errors, so avoid repeating types
14501493
foreach t1 = AllVecs in

0 commit comments

Comments
 (0)