r175045 - Emit virtual/deleting destructors properly with -cxx-abi microsoft, PR15058

Timur Iskhodzhanov timurrrr at google.com
Wed Feb 13 04:26:50 PST 2013


... and r175054 too.

Is there an easy way to test all possible LL variable namings?
Release, Release+Asserts, anything else?

2013/2/13 Timur Iskhodzhanov <timurrrr at google.com>:
> 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