r175045 - Emit virtual/deleting destructors properly with -cxx-abi microsoft, PR15058
Timur Iskhodzhanov
timurrrr at google.com
Wed Feb 13 04:18:53 PST 2013
Should be fixed by r175053.
Never knew the Release build generates different names and a different
format for label definitions...
John - just FYI, hope the test change is ok.
2013/2/13 Timur Iskhodzhanov <timurrrr at google.com>:
> I see the problem, will fix soon.
>
> 2013/2/13 Timur Iskhodzhanov <timurrrr at google.com>:
>> Ah, I was never running Release, only Release+Asserts or Debug.
>> Looking...
>> Is this OK if Release actually generates a different .ll?
>> Timur Iskhodzhanov,
>> Google Russia
>>
>>
>>
>> 2013/2/13 NAKAMURA Takumi <geek4civic at gmail.com>:
>>> It could be reproducible with -Asserts.
>>>
>>> 2013/2/13 Timur Iskhodzhanov <timurrrr at google.com>:
>>>> Hi Takumi,
>>>>
>>>> This change seems to work differently on your bot:
>>>> http://bb.pgr.jp/builders/clang-3stage-x86_64-linux/builds/1033/steps/test_clang/logs/Clang%20%3A%3A%20CodeGenCXX___microsoft-abi-structors.cpp
>>>>
>>>> /home/bb/clang-3stage-x86_64-linux/builds/stagen/Release/bin/clang
>>>> -cc1 -internal-isystem
>>>> /home/bb/clang-3stage-x86_64-linux/builds/stagen/Release/bin/../lib/clang/3.3/include
>>>> -emit-llvm /home/bb/clang-3stage-x86_64-linux/llvm-project/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
>>>> -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti >
>>>> /home/bb/clang-3stage-x86_64-linux/builds/stagen/tools/clang/test/CodeGenCXX/Output/microsoft-abi-structors.cpp.tmp
>>>> 2>&1
>>>> FileCheck /home/bb/clang-3stage-x86_64-linux/llvm-project/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
>>>> < /home/bb/clang-3stage-x86_64-linux/builds/stagen/tools/clang/test/CodeGenCXX/Output/microsoft-abi-structors.cpp.tmp
>>>> FileCheck --check-prefix=DTORS
>>>> /home/bb/clang-3stage-x86_64-linux/llvm-project/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
>>>> < /home/bb/clang-3stage-x86_64-linux/builds/stagen/tools/clang/test/CodeGenCXX/Output/microsoft-abi-structors.cpp.tmp
>>>> --
>>>> Exit Code: 1
>>>> Command Output (stderr):
>>>> --
>>>> /home/bb/clang-3stage-x86_64-linux/llvm-project/clang/test/CodeGenCXX/microsoft-abi-structors.cpp:36:11:
>>>> error: expected string not found in input
>>>> // DTORS: %0 = icmp eq i8 %should_call_delete{{.*}}, 0
>>>> ^
>>>> <stdin>:108:114: note: scanning from here
>>>> define linkonce_odr x86_thiscallcc void
>>>> @"\01??_GB@@UAEPAXI at Z"(%struct.B* %this, i1 zeroext
>>>> %should_call_delete) unnamed_addr nounwind align 2 {
>>>>
>>>> ^
>>>> <stdin>:112:2: note: possible intended match here
>>>> %3 = zext i1 %should_call_delete to i8
>>>> ^
>>>> --
>>>>
>>>> Any idea what's up and how to fix?
>>>> Some .ll context would help...
>>>>
>>>> I can't repro locally on Linux, Mac and Windows.
>>>>
>>>> --
>>>> Timur Iskhodzhanov,
>>>> Google Russia
>>>>
>>>>
>>>>
>>>> 2013/2/13 Timur Iskhodzhanov <timurrrr at google.com>:
>>>>> Author: timurrrr
>>>>> Date: Wed Feb 13 02:37:51 2013
>>>>> New Revision: 175045
>>>>>
>>>>> URL: http://llvm.org/viewvc/llvm-project?rev=175045&view=rev
>>>>> Log:
>>>>> Emit virtual/deleting destructors properly with -cxx-abi microsoft, PR15058
>>>>>
>>>>> Modified:
>>>>> cfe/trunk/lib/AST/MicrosoftMangle.cpp
>>>>> cfe/trunk/lib/AST/VTableBuilder.cpp
>>>>> cfe/trunk/lib/CodeGen/CGCXXABI.h
>>>>> cfe/trunk/lib/CodeGen/CGClass.cpp
>>>>> cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>>>>> cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>>>>> cfe/trunk/lib/CodeGen/CodeGenFunction.h
>>>>> cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>>>>> cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
>>>>> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
>>>>>
>>>>> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
>>>>> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Wed Feb 13 02:37:51 2013
>>>>> @@ -28,12 +28,25 @@ using namespace clang;
>>>>>
>>>>> namespace {
>>>>>
>>>>> +static const FunctionDecl *getStructor(const FunctionDecl *fn) {
>>>>> + if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
>>>>> + return ftd->getTemplatedDecl();
>>>>> +
>>>>> + return fn;
>>>>> +}
>>>>> +
>>>>> /// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
>>>>> /// Microsoft Visual C++ ABI.
>>>>> class MicrosoftCXXNameMangler {
>>>>> MangleContext &Context;
>>>>> raw_ostream &Out;
>>>>>
>>>>> + /// The "structor" is the top-level declaration being mangled, if
>>>>> + /// that's not a template specialization; otherwise it's the pattern
>>>>> + /// for that specialization.
>>>>> + const NamedDecl *Structor;
>>>>> + unsigned StructorType;
>>>>> +
>>>>> // FIXME: audit the performance of BackRefMap as it might do way too many
>>>>> // copying of strings.
>>>>> typedef std::map<std::string, unsigned> BackRefMap;
>>>>> @@ -47,7 +60,15 @@ class MicrosoftCXXNameMangler {
>>>>>
>>>>> public:
>>>>> MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
>>>>> - : Context(C), Out(Out_), UseNameBackReferences(true) { }
>>>>> + : Context(C), Out(Out_),
>>>>> + Structor(0), StructorType(-1),
>>>>> + UseNameBackReferences(true) { }
>>>>> +
>>>>> + MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_,
>>>>> + const CXXDestructorDecl *D, CXXDtorType Type)
>>>>> + : Context(C), Out(Out_),
>>>>> + Structor(getStructor(D)), StructorType(Type),
>>>>> + UseNameBackReferences(true) { }
>>>>>
>>>>> raw_ostream &getStream() const { return Out; }
>>>>>
>>>>> @@ -68,6 +89,7 @@ private:
>>>>> void mangleSourceName(const IdentifierInfo *II);
>>>>> void manglePostfix(const DeclContext *DC, bool NoFunction=false);
>>>>> void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
>>>>> + void mangleCXXDtorType(CXXDtorType T);
>>>>> void mangleQualifiers(Qualifiers Quals, bool IsMember);
>>>>> void manglePointerQualifiers(Qualifiers Quals);
>>>>>
>>>>> @@ -485,7 +507,14 @@ MicrosoftCXXNameMangler::mangleUnqualifi
>>>>> break;
>>>>>
>>>>> case DeclarationName::CXXDestructorName:
>>>>> - Out << "?1";
>>>>> + if (ND == Structor)
>>>>> + // If the named decl is the C++ destructor we're mangling,
>>>>> + // use the type we were given.
>>>>> + mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
>>>>> + else
>>>>> + // Otherwise, use the complete destructor name. This is relevant if a
>>>>> + // class with a destructor is declared within a destructor.
>>>>> + mangleCXXDtorType(Dtor_Complete);
>>>>> break;
>>>>>
>>>>> case DeclarationName::CXXConversionFunctionName:
>>>>> @@ -543,6 +572,23 @@ void MicrosoftCXXNameMangler::manglePost
>>>>> }
>>>>> }
>>>>>
>>>>> +void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
>>>>> + switch (T) {
>>>>> + case Dtor_Deleting:
>>>>> + Out << "?_G";
>>>>> + return;
>>>>> + case Dtor_Base:
>>>>> + // FIXME: We should be asked to mangle base dtors.
>>>>> + // However, fixing this would require larger changes to the CodeGenModule.
>>>>> + // Please put llvm_unreachable here when CGM is changed.
>>>>> + // For now, just mangle a base dtor the same way as a complete dtor...
>>>>> + case Dtor_Complete:
>>>>> + Out << "?1";
>>>>> + return;
>>>>> + }
>>>>> + llvm_unreachable("Unsupported dtor type?");
>>>>> +}
>>>>> +
>>>>> void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
>>>>> SourceLocation Loc) {
>>>>> switch (OO) {
>>>>> @@ -1110,9 +1156,18 @@ void MicrosoftCXXNameMangler::mangleType
>>>>>
>>>>> // <return-type> ::= <type>
>>>>> // ::= @ # structors (they have no declared return type)
>>>>> - if (IsStructor)
>>>>> + if (IsStructor) {
>>>>> + if (isa<CXXDestructorDecl>(D) && D == Structor &&
>>>>> + StructorType == Dtor_Deleting) {
>>>>> + // The scalar deleting destructor takes an extra int argument.
>>>>> + // However, the FunctionType generated has 0 arguments.
>>>>> + // FIXME: This is a temporary hack.
>>>>> + // Maybe should fix the FunctionType creation instead?
>>>>> + Out << "PAXI at Z";
>>>>> + return;
>>>>> + }
>>>>> Out << '@';
>>>>> - else {
>>>>> + } else {
>>>>> QualType Result = Proto->getResultType();
>>>>> const Type* RT = Result.getTypePtr();
>>>>> if (!RT->isAnyPointerType() && !RT->isReferenceType()) {
>>>>> @@ -1711,7 +1766,7 @@ void MicrosoftMangleContext::mangleCXXCt
>>>>> void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
>>>>> CXXDtorType Type,
>>>>> raw_ostream & Out) {
>>>>> - MicrosoftCXXNameMangler mangler(*this, Out);
>>>>> + MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
>>>>> mangler.mangle(D);
>>>>> }
>>>>> void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD,
>>>>>
>>>>> Modified: cfe/trunk/lib/AST/VTableBuilder.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/lib/AST/VTableBuilder.cpp (original)
>>>>> +++ cfe/trunk/lib/AST/VTableBuilder.cpp Wed Feb 13 02:37:51 2013
>>>>> @@ -1160,6 +1160,8 @@ void VTableBuilder::ComputeThisAdjustmen
>>>>> break;
>>>>> case VTableComponent::CK_DeletingDtorPointer:
>>>>> // We've already added the thunk when we saw the complete dtor pointer.
>>>>> + // FIXME: check how this works in the Microsoft ABI
>>>>> + // while working on the multiple inheritance patch.
>>>>> continue;
>>>>> }
>>>>>
>>>>> @@ -1302,11 +1304,8 @@ VTableBuilder::AddMethod(const CXXMethod
>>>>> Components.push_back(VTableComponent::MakeCompleteDtor(DD));
>>>>> Components.push_back(VTableComponent::MakeDeletingDtor(DD));
>>>>> } else {
>>>>> - // Add only one destructor in MS mode.
>>>>> - // FIXME: The virtual destructors are handled differently in MS ABI,
>>>>> - // we should add such a support later. For now, put the complete
>>>>> - // destructor into the vftable just to make its layout right.
>>>>> - Components.push_back(VTableComponent::MakeCompleteDtor(DD));
>>>>> + // Add the scalar deleting destructor.
>>>>> + Components.push_back(VTableComponent::MakeDeletingDtor(DD));
>>>>> }
>>>>> } else {
>>>>> // Add the return adjustment if necessary.
>>>>> @@ -1951,6 +1950,8 @@ void VTableBuilder::dumpLayout(raw_ostre
>>>>> Out << DD->getQualifiedNameAsString();
>>>>> if (IsComplete)
>>>>> Out << "() [complete]";
>>>>> + else if (isMicrosoftABI())
>>>>> + Out << "() [scalar deleting]";
>>>>> else
>>>>> Out << "() [deleting]";
>>>>>
>>>>> @@ -2142,8 +2143,8 @@ void VTableBuilder::dumpLayout(raw_ostre
>>>>> IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))]
>>>>> = MethodName + " [deleting]";
>>>>> } else {
>>>>> - IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))]
>>>>> - = MethodName;
>>>>> + IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))]
>>>>> + = MethodName + " [scalar deleting]";
>>>>> }
>>>>> } else {
>>>>> IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName;
>>>>> @@ -2275,8 +2276,9 @@ void VTableContext::ComputeMethodVTableI
>>>>> MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
>>>>> getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
>>>>> } else {
>>>>> - MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
>>>>> - getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
>>>>> + // Add the scalar deleting destructor.
>>>>> + MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
>>>>> + getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
>>>>> }
>>>>> } else {
>>>>> MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD);
>>>>> @@ -2302,11 +2304,8 @@ void VTableContext::ComputeMethodVTableI
>>>>> // Add the deleting dtor.
>>>>> MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
>>>>> } else {
>>>>> - // Add only the deleting dtor.
>>>>> - // FIXME: The virtual destructors are handled differently in MS ABI,
>>>>> - // we should add such a support later. For now, put the complete
>>>>> - // destructor into the vftable indices.
>>>>> - MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
>>>>> + // Add the scalar deleting dtor.
>>>>> + MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
>>>>> }
>>>>> } else {
>>>>> // Add the entry.
>>>>>
>>>>> Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
>>>>> +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Wed Feb 13 02:37:51 2013
>>>>> @@ -54,11 +54,20 @@ protected:
>>>>> return CGF.CXXABIThisValue;
>>>>> }
>>>>>
>>>>> + // FIXME: Every place that calls getVTT{Decl,Value} is something
>>>>> + // that needs to be abstracted properly.
>>>>> ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) {
>>>>> - return CGF.CXXVTTDecl;
>>>>> + return CGF.CXXStructorImplicitParamDecl;
>>>>> }
>>>>> llvm::Value *&getVTTValue(CodeGenFunction &CGF) {
>>>>> - return CGF.CXXVTTValue;
>>>>> + return CGF.CXXStructorImplicitParamValue;
>>>>> + }
>>>>> +
>>>>> + ImplicitParamDecl *&getStructorImplicitParamDecl(CodeGenFunction &CGF) {
>>>>> + return CGF.CXXStructorImplicitParamDecl;
>>>>> + }
>>>>> + llvm::Value *&getStructorImplicitParamValue(CodeGenFunction &CGF) {
>>>>> + return CGF.CXXStructorImplicitParamValue;
>>>>> }
>>>>>
>>>>> /// Build a parameter variable suitable for 'this'.
>>>>>
>>>>> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
>>>>> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Feb 13 02:37:51 2013
>>>>> @@ -953,6 +953,32 @@ namespace {
>>>>> }
>>>>> };
>>>>>
>>>>> + struct CallDtorDeleteConditional : EHScopeStack::Cleanup {
>>>>> + llvm::Value *ShouldDeleteCondition;
>>>>> + public:
>>>>> + CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
>>>>> + : ShouldDeleteCondition(ShouldDeleteCondition) {
>>>>> + assert(ShouldDeleteCondition != NULL);
>>>>> + }
>>>>> +
>>>>> + void Emit(CodeGenFunction &CGF, Flags flags) {
>>>>> + llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
>>>>> + llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
>>>>> + llvm::Value *ShouldCallDelete
>>>>> + = CGF.Builder.CreateIsNull(ShouldDeleteCondition);
>>>>> + CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
>>>>> +
>>>>> + CGF.EmitBlock(callDeleteBB);
>>>>> + const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
>>>>> + const CXXRecordDecl *ClassDecl = Dtor->getParent();
>>>>> + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(),
>>>>> + CGF.getContext().getTagDeclType(ClassDecl));
>>>>> + CGF.Builder.CreateBr(continueBB);
>>>>> +
>>>>> + CGF.EmitBlock(continueBB);
>>>>> + }
>>>>> + };
>>>>> +
>>>>> class DestroyField : public EHScopeStack::Cleanup {
>>>>> const FieldDecl *field;
>>>>> CodeGenFunction::Destroyer *destroyer;
>>>>> @@ -991,7 +1017,14 @@ void CodeGenFunction::EnterDtorCleanups(
>>>>> if (DtorType == Dtor_Deleting) {
>>>>> assert(DD->getOperatorDelete() &&
>>>>> "operator delete missing - EmitDtorEpilogue");
>>>>> - EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
>>>>> + if (CXXStructorImplicitParamValue) {
>>>>> + // If there is an implicit param to the deleting dtor, it's a boolean
>>>>> + // telling whether we should call delete at the end of the dtor.
>>>>> + EHStack.pushCleanup<CallDtorDeleteConditional>(
>>>>> + NormalAndEHCleanup, CXXStructorImplicitParamValue);
>>>>> + } else {
>>>>> + EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
>>>>> + }
>>>>> return;
>>>>> }
>>>>>
>>>>> @@ -1243,7 +1276,8 @@ CodeGenFunction::EmitCXXConstructorCall(
>>>>>
>>>>> // FIXME: Provide a source location here.
>>>>> EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
>>>>> - VTT, ArgBeg, ArgEnd);
>>>>> + VTT, getContext().getPointerType(getContext().VoidPtrTy),
>>>>> + ArgBeg, ArgEnd);
>>>>> }
>>>>>
>>>>> void
>>>>> @@ -1399,7 +1433,8 @@ void CodeGenFunction::EmitCXXDestructorC
>>>>>
>>>>> // FIXME: Provide a source location here.
>>>>> EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
>>>>> - VTT, 0, 0);
>>>>> + VTT, getContext().getPointerType(getContext().VoidPtrTy),
>>>>> + 0, 0);
>>>>> }
>>>>>
>>>>> namespace {
>>>>>
>>>>> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
>>>>> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Feb 13 02:37:51 2013
>>>>> @@ -28,7 +28,8 @@ RValue CodeGenFunction::EmitCXXMemberCal
>>>>> llvm::Value *Callee,
>>>>> ReturnValueSlot ReturnValue,
>>>>> llvm::Value *This,
>>>>> - llvm::Value *VTT,
>>>>> + llvm::Value *ImplicitParam,
>>>>> + QualType ImplicitParamTy,
>>>>> CallExpr::const_arg_iterator ArgBeg,
>>>>> CallExpr::const_arg_iterator ArgEnd) {
>>>>> assert(MD->isInstance() &&
>>>>> @@ -46,10 +47,9 @@ RValue CodeGenFunction::EmitCXXMemberCal
>>>>> // Push the this ptr.
>>>>> Args.add(RValue::get(This), MD->getThisType(getContext()));
>>>>>
>>>>> - // If there is a VTT parameter, emit it.
>>>>> - if (VTT) {
>>>>> - QualType T = getContext().getPointerType(getContext().VoidPtrTy);
>>>>> - Args.add(RValue::get(VTT), T);
>>>>> + // If there is an implicit parameter (e.g. VTT), emit it.
>>>>> + if (ImplicitParam) {
>>>>> + Args.add(RValue::get(ImplicitParam), ImplicitParamTy);
>>>>> }
>>>>>
>>>>> const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
>>>>> @@ -316,7 +316,8 @@ RValue CodeGenFunction::EmitCXXMemberCal
>>>>> }
>>>>>
>>>>> return EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
>>>>> - /*VTT=*/0, CE->arg_begin(), CE->arg_end());
>>>>> + /*ImplicitParam=*/0, QualType(),
>>>>> + CE->arg_begin(), CE->arg_end());
>>>>> }
>>>>>
>>>>> RValue
>>>>> @@ -388,7 +389,8 @@ CodeGenFunction::EmitCXXOperatorMemberCa
>>>>>
>>>>> llvm::Value *Callee = EmitCXXOperatorMemberCallee(E, MD, This);
>>>>> return EmitCXXMemberCall(MD, E->getExprLoc(), Callee, ReturnValue, This,
>>>>> - /*VTT=*/0, E->arg_begin() + 1, E->arg_end());
>>>>> + /*ImplicitParam=*/0, QualType(),
>>>>> + E->arg_begin() + 1, E->arg_end());
>>>>> }
>>>>>
>>>>> RValue CodeGenFunction::EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E,
>>>>> @@ -1408,7 +1410,7 @@ static void EmitObjectDelete(CodeGenFunc
>>>>> Ptr, Ty);
>>>>> // FIXME: Provide a source location here.
>>>>> CGF.EmitCXXMemberCall(Dtor, SourceLocation(), Callee, ReturnValueSlot(),
>>>>> - Ptr, /*VTT=*/0, 0, 0);
>>>>> + Ptr, /*ImplicitParam=*/0, QualType(), 0, 0);
>>>>>
>>>>> if (UseGlobalDelete) {
>>>>> CGF.PopCleanupBlock();
>>>>>
>>>>> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
>>>>> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Feb 13 02:37:51 2013
>>>>> @@ -43,8 +43,9 @@ CodeGenFunction::CodeGenFunction(CodeGen
>>>>> FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0),
>>>>> DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false),
>>>>> IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),
>>>>> - CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), CXXVTTDecl(0),
>>>>> - CXXVTTValue(0), OutermostConditional(0), TerminateLandingPad(0),
>>>>> + CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),
>>>>> + CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),
>>>>> + OutermostConditional(0), TerminateLandingPad(0),
>>>>> TerminateHandler(0), TrapBB(0) {
>>>>> if (!suppressNewContext)
>>>>> CGM.getCXXABI().getMangleContext().startNewFunction();
>>>>>
>>>>> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
>>>>> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Feb 13 02:37:51 2013
>>>>> @@ -1179,11 +1179,10 @@ private:
>>>>> llvm::Value *CXXABIThisValue;
>>>>> llvm::Value *CXXThisValue;
>>>>>
>>>>> - /// CXXVTTDecl - When generating code for a base object constructor or
>>>>> - /// base object destructor with virtual bases, this will hold the implicit
>>>>> - /// VTT parameter.
>>>>> - ImplicitParamDecl *CXXVTTDecl;
>>>>> - llvm::Value *CXXVTTValue;
>>>>> + /// CXXStructorImplicitParamDecl - When generating code for a constructor or
>>>>> + /// destructor, this will hold the implicit argument (e.g. VTT).
>>>>> + ImplicitParamDecl *CXXStructorImplicitParamDecl;
>>>>> + llvm::Value *CXXStructorImplicitParamValue;
>>>>>
>>>>> /// OutermostConditional - Points to the outermost active
>>>>> /// conditional control. This is used so that we know if a
>>>>> @@ -1777,9 +1776,19 @@ public:
>>>>>
>>>>> /// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have
>>>>> /// virtual bases.
>>>>> + // FIXME: Every place that calls LoadCXXVTT is something
>>>>> + // that needs to be abstracted properly.
>>>>> llvm::Value *LoadCXXVTT() {
>>>>> - assert(CXXVTTValue && "no VTT value for this function");
>>>>> - return CXXVTTValue;
>>>>> + assert(CXXStructorImplicitParamValue && "no VTT value for this function");
>>>>> + return CXXStructorImplicitParamValue;
>>>>> + }
>>>>> +
>>>>> + /// LoadCXXStructorImplicitParam - Load the implicit parameter
>>>>> + /// for a constructor/destructor.
>>>>> + llvm::Value *LoadCXXStructorImplicitParam() {
>>>>> + assert(CXXStructorImplicitParamValue &&
>>>>> + "no implicit argument value for this function");
>>>>> + return CXXStructorImplicitParamValue;
>>>>> }
>>>>>
>>>>> /// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a
>>>>> @@ -2294,7 +2303,8 @@ public:
>>>>> llvm::Value *Callee,
>>>>> ReturnValueSlot ReturnValue,
>>>>> llvm::Value *This,
>>>>> - llvm::Value *VTT,
>>>>> + llvm::Value *ImplicitParam,
>>>>> + QualType ImplicitParamTy,
>>>>> CallExpr::const_arg_iterator ArgBeg,
>>>>> CallExpr::const_arg_iterator ArgEnd);
>>>>> RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
>>>>>
>>>>> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
>>>>> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Wed Feb 13 02:37:51 2013
>>>>> @@ -45,10 +45,7 @@ public:
>>>>> void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
>>>>> CXXDtorType Type,
>>>>> CanQualType &ResTy,
>>>>> - SmallVectorImpl<CanQualType> &ArgTys) {
>>>>> - // 'this' is already in place
>>>>> - // TODO: 'for base' flag
>>>>> - }
>>>>> + SmallVectorImpl<CanQualType> &ArgTys);
>>>>>
>>>>> void BuildInstanceFunctionParams(CodeGenFunction &CGF,
>>>>> QualType &ResTy,
>>>>> @@ -121,6 +118,27 @@ void MicrosoftCXXABI::BuildConstructorSi
>>>>> ResTy = ArgTys[0];
>>>>> }
>>>>>
>>>>> +void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
>>>>> + CXXDtorType Type,
>>>>> + CanQualType &ResTy,
>>>>> + SmallVectorImpl<CanQualType> &ArgTys) {
>>>>> + // 'this' is already in place
>>>>> + // TODO: 'for base' flag
>>>>> +
>>>>> + if (Type == Dtor_Deleting) {
>>>>> + // The scalar deleting destructor takes an implicit bool parameter.
>>>>> + ArgTys.push_back(CGM.getContext().BoolTy);
>>>>> + }
>>>>> +}
>>>>> +
>>>>> +static bool IsDeletingDtor(GlobalDecl GD) {
>>>>> + const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
>>>>> + if (isa<CXXDestructorDecl>(MD)) {
>>>>> + return GD.getDtorType() == Dtor_Deleting;
>>>>> + }
>>>>> + return false;
>>>>> +}
>>>>> +
>>>>> void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
>>>>> QualType &ResTy,
>>>>> FunctionArgList &Params) {
>>>>> @@ -128,6 +146,17 @@ void MicrosoftCXXABI::BuildInstanceFunct
>>>>> if (needThisReturn(CGF.CurGD)) {
>>>>> ResTy = Params[0]->getType();
>>>>> }
>>>>> + if (IsDeletingDtor(CGF.CurGD)) {
>>>>> + ASTContext &Context = getContext();
>>>>> +
>>>>> + ImplicitParamDecl *ShouldDelete
>>>>> + = ImplicitParamDecl::Create(Context, 0,
>>>>> + CGF.CurGD.getDecl()->getLocation(),
>>>>> + &Context.Idents.get("should_call_delete"),
>>>>> + Context.BoolTy);
>>>>> + Params.push_back(ShouldDelete);
>>>>> + getStructorImplicitParamDecl(CGF) = ShouldDelete;
>>>>> + }
>>>>> }
>>>>>
>>>>> void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
>>>>> @@ -135,6 +164,14 @@ void MicrosoftCXXABI::EmitInstanceFuncti
>>>>> if (needThisReturn(CGF.CurGD)) {
>>>>> CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
>>>>> }
>>>>> + if (IsDeletingDtor(CGF.CurGD)) {
>>>>> + assert(getStructorImplicitParamDecl(CGF) &&
>>>>> + "no implicit parameter for a deleting destructor?");
>>>>> + getStructorImplicitParamValue(CGF)
>>>>> + = CGF.Builder.CreateLoad(
>>>>> + CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
>>>>> + "should_call_delete");
>>>>> + }
>>>>> }
>>>>>
>>>>> bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
>>>>>
>>>>> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original)
>>>>> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Wed Feb 13 02:37:51 2013
>>>>> @@ -1,4 +1,8 @@
>>>>> -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
>>>>> +// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti > %t 2>&1
>>>>> +// RUN: FileCheck %s < %t
>>>>> +// Using a different check prefix as the inline destructors might be placed
>>>>> +// anywhere in the output.
>>>>> +// RUN: FileCheck --check-prefix=DTORS %s < %t
>>>>>
>>>>> class A {
>>>>> public:
>>>>> @@ -23,13 +27,60 @@ void no_constructor_destructor_infinite_
>>>>> }
>>>>>
>>>>> struct B {
>>>>> - virtual ~B();
>>>>> + virtual ~B() {
>>>>> +// Complete destructor first:
>>>>> +// DTORS: define {{.*}} x86_thiscallcc void @"\01??1B@@UAE at XZ"(%struct.B* %this)
>>>>> +//
>>>>> +// Then, the scalar deleting destructor (used in the vtable):
>>>>> +// DTORS: define {{.*}} x86_thiscallcc void @"\01??_GB@@UAEPAXI at Z"(%struct.B* %this, i1 zeroext %should_call_delete)
>>>>> +// DTORS: %0 = icmp eq i8 %should_call_delete{{.*}}, 0
>>>>> +// DTORS-NEXT: br i1 %0, label %dtor.continue, label %dtor.call_delete
>>>>> +// DTORS: dtor.call_delete:
>>>>> +// DTORS-NEXT: %1 = bitcast %struct.B* %this1 to i8*
>>>>> +// DTORS-NEXT: call void @"\01??3 at YAXPAX@Z"(i8* %1) nounwind
>>>>> +// DTORS-NEXT: br label %dtor.continue
>>>>> +// DTORS: dtor.continue:
>>>>> +// DTORS-NEXT: ret void
>>>>> + }
>>>>> virtual void foo();
>>>>> };
>>>>>
>>>>> +// Emits the vftable in the output.
>>>>> +void B::foo() {}
>>>>> +
>>>>> void check_vftable_offset() {
>>>>> B b;
>>>>> // The vftable pointer should point at the beginning of the vftable.
>>>>> // CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %struct.B* {{.*}} to i8***
>>>>> // CHECK: store i8** getelementptr inbounds ([2 x i8*]* @"\01??_7B@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]]
>>>>> }
>>>>> +
>>>>> +// FIXME: Enable the following block and add expectations when calls
>>>>> +// to virtual complete dtor are supported.
>>>>> +#if 0
>>>>> +void call_complete_dtor(B *obj_ptr) {
>>>>> + obj_ptr->~B();
>>>>> +}
>>>>> +#endif
>>>>> +
>>>>> +void call_deleting_dtor(B *obj_ptr) {
>>>>> +// FIXME: Add CHECKs when calls to virtual deleting dtor are generated properly.
>>>>> + delete obj_ptr;
>>>>> +}
>>>>> +
>>>>> +struct C {
>>>>> + static int foo();
>>>>> +
>>>>> + C() {
>>>>> + static int ctor_static = foo();
>>>>> + // CHECK that the static in the ctor gets mangled correctly:
>>>>> + // CHECK: @"\01?ctor_static@?1???0C@@QAE at XZ@4HA"
>>>>> + }
>>>>> + ~C() {
>>>>> + static int dtor_static = foo();
>>>>> + // CHECK that the static in the dtor gets mangled correctly:
>>>>> + // CHECK: @"\01?dtor_static@?1???1C@@QAE at XZ@4HA"
>>>>> + }
>>>>> +};
>>>>> +
>>>>> +void use_C() { C c; }
>>>>>
>>>>> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp?rev=175045&r1=175044&r2=175045&view=diff
>>>>> ==============================================================================
>>>>> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (original)
>>>>> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp Wed Feb 13 02:37:51 2013
>>>>> @@ -37,10 +37,10 @@ void B::f() {}
>>>>>
>>>>> struct C {
>>>>> // CHECK-C: Vtable for 'C' (2 entries)
>>>>> - // CHECK-C-NEXT: 0 | C::~C()
>>>>> + // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
>>>>> // CHECK-C-NEXT: 1 | void C::f()
>>>>> // CHECK-C: VTable indices for 'C' (2 entries).
>>>>> - // CHECK-C-NEXT: 0 | C::~C()
>>>>> + // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
>>>>> // CHECK-C-NEXT: 1 | void C::f()
>>>>> // Never used, so doesn't emit a vtable.
>>>>> virtual ~C();
>>>>> @@ -52,7 +52,7 @@ void C::f() {}
>>>>> struct D {
>>>>> // CHECK-D: Vtable for 'D' (2 entries)
>>>>> // CHECK-D-NEXT: 0 | void D::f()
>>>>> - // CHECK-D-NEXT: 1 | D::~D()
>>>>> + // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
>>>>> // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*]
>>>>> virtual void f();
>>>>>
>>>>> @@ -65,10 +65,10 @@ struct E : A {
>>>>> // CHECK-E-NEXT: 0 | void A::f()
>>>>> // CHECK-E-NEXT: 1 | void A::g()
>>>>> // CHECK-E-NEXT: 2 | void A::h()
>>>>> - // CHECK-E-NEXT: 3 | E::~E()
>>>>> + // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
>>>>> // CHECK-E-NEXT: 4 | void E::i()
>>>>> // CHECK-E: VTable indices for 'E' (2 entries).
>>>>> - // CHECK-E-NEXT: 3 | E::~E()
>>>>> + // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
>>>>> // CHECK-E-NEXT: 4 | void E::i()
>>>>>
>>>>> // Never used, so doesn't emit a vtable.
>>>>> @@ -83,10 +83,10 @@ struct F : A {
>>>>> // CHECK-F-NEXT: 1 | void A::g()
>>>>> // CHECK-F-NEXT: 2 | void A::h()
>>>>> // CHECK-F-NEXT: 3 | void F::i()
>>>>> - // CHECK-F-NEXT: 4 | F::~F()
>>>>> + // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
>>>>> // CHECK-F: VTable indices for 'F' (2 entries).
>>>>> // CHECK-F-NEXT: 3 | void F::i()
>>>>> - // CHECK-F-NEXT: 4 | F::~F()
>>>>> + // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
>>>>> // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*]
>>>>> virtual void i();
>>>>> virtual ~F();
>>>>> @@ -98,12 +98,12 @@ struct G : E {
>>>>> // CHECK-G-NEXT: 0 | void G::f()
>>>>> // CHECK-G-NEXT: 1 | void A::g()
>>>>> // CHECK-G-NEXT: 2 | void A::h()
>>>>> - // CHECK-G-NEXT: 3 | G::~G()
>>>>> + // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
>>>>> // CHECK-G-NEXT: 4 | void E::i()
>>>>> // CHECK-G-NEXT: 5 | void G::j()
>>>>> // CHECK-G: VTable indices for 'G' (3 entries).
>>>>> // CHECK-G-NEXT: 0 | void G::f()
>>>>> - // CHECK-G-NEXT: 3 | G::~G()
>>>>> + // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
>>>>> // CHECK-G-NEXT: 5 | void G::j()
>>>>> // Never used, so doesn't emit a vtable.
>>>>> virtual void f(); // overrides A::f()
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> cfe-commits mailing list
>>>>> cfe-commits at cs.uiuc.edu
>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list