diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 | 
| commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
| tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /clang/lib/CodeGen/ItaniumCXXABI.cpp | |
| parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) | |
Notes
Diffstat (limited to 'clang/lib/CodeGen/ItaniumCXXABI.cpp')
| -rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 367 | 
1 files changed, 282 insertions, 85 deletions
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index b5b8702c551e..80de2a6e3950 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -203,7 +203,7 @@ public:    void EmitCXXConstructors(const CXXConstructorDecl *D) override; -  AddedStructorArgs +  AddedStructorArgCounts    buildStructorSignature(GlobalDecl GD,                           SmallVectorImpl<CanQualType> &ArgTys) override; @@ -222,10 +222,17 @@ public:    void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override; -  AddedStructorArgs -  addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, -                             CXXCtorType Type, bool ForVirtualBase, -                             bool Delegating, CallArgList &Args) override; +  AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF, +                                               const CXXConstructorDecl *D, +                                               CXXCtorType Type, +                                               bool ForVirtualBase, +                                               bool Delegating) override; + +  llvm::Value *getCXXDestructorImplicitParam(CodeGenFunction &CGF, +                                             const CXXDestructorDecl *DD, +                                             CXXDtorType Type, +                                             bool ForVirtualBase, +                                             bool Delegating) override;    void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,                            CXXDtorType Type, bool ForVirtualBase, @@ -516,6 +523,22 @@ private:    }    bool canCallMismatchedFunctionType() const override { return false; }  }; + +class XLCXXABI final : public ItaniumCXXABI { +public: +  explicit XLCXXABI(CodeGen::CodeGenModule &CGM) +      : ItaniumCXXABI(CGM) {} + +  void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, +                          llvm::FunctionCallee dtor, +                          llvm::Constant *addr) override; + +  bool useSinitAndSterm() const override { return true; } + +private: +  void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub, +                             llvm::Constant *addr); +};  }  CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { @@ -546,6 +569,9 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {    case TargetCXXABI::WebAssembly:      return new WebAssemblyCXXABI(CGM); +  case TargetCXXABI::XL: +    return new XLCXXABI(CGM); +    case TargetCXXABI::GenericItanium:      if (CGM.getContext().getTargetInfo().getTriple().getArch()          == llvm::Triple::le32) { @@ -670,6 +696,10 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(                              CGM.HasHiddenLTOVisibility(RD);    bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&                             CGM.HasHiddenLTOVisibility(RD); +  bool ShouldEmitWPDInfo = +      CGM.getCodeGenOpts().WholeProgramVTables && +      // Don't insert type tests if we are forcing public std visibility. +      !CGM.HasLTOVisibilityPublicStd(RD);    llvm::Value *VirtualFn = nullptr;    { @@ -677,16 +707,17 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(      llvm::Value *TypeId = nullptr;      llvm::Value *CheckResult = nullptr; -    if (ShouldEmitCFICheck || ShouldEmitVFEInfo) { -      // If doing CFI or VFE, we will need the metadata node to check against. +    if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) { +      // If doing CFI, VFE or WPD, we will need the metadata node to check +      // against.        llvm::Metadata *MD =            CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));        TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);      } -    llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); -      if (ShouldEmitVFEInfo) { +      llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); +        // If doing VFE, load from the vtable with a type.checked.load intrinsic        // call. Note that we use the GEP to calculate the address to load from        // and pass 0 as the offset to the intrinsic. This is because every @@ -702,18 +733,30 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(      } else {        // When not doing VFE, emit a normal load, as it allows more        // optimisations than type.checked.load. -      if (ShouldEmitCFICheck) { +      if (ShouldEmitCFICheck || ShouldEmitWPDInfo) { +        llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);          CheckResult = Builder.CreateCall(              CGM.getIntrinsic(llvm::Intrinsic::type_test),              {Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});        } -      VFPAddr = -          Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo()); -      VirtualFn = Builder.CreateAlignedLoad(VFPAddr, CGF.getPointerAlign(), -                                            "memptr.virtualfn"); + +      if (CGM.getItaniumVTableContext().isRelativeLayout()) { +        VirtualFn = CGF.Builder.CreateCall( +            CGM.getIntrinsic(llvm::Intrinsic::load_relative, +                             {VTableOffset->getType()}), +            {VTable, VTableOffset}); +        VirtualFn = CGF.Builder.CreateBitCast(VirtualFn, FTy->getPointerTo()); +      } else { +        llvm::Value *VFPAddr = CGF.Builder.CreateGEP(VTable, VTableOffset); +        VFPAddr = CGF.Builder.CreateBitCast( +            VFPAddr, FTy->getPointerTo()->getPointerTo()); +        VirtualFn = CGF.Builder.CreateAlignedLoad( +            VFPAddr, CGF.getPointerAlign(), "memptr.virtualfn"); +      }      }      assert(VirtualFn && "Virtual fuction pointer not created!"); -    assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || CheckResult) && +    assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo || +            CheckResult) &&             "Check result required but not created!");      if (ShouldEmitCFICheck) { @@ -984,11 +1027,16 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,    llvm::Constant *MemPtr[2];    if (MD->isVirtual()) {      uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD); - -    const ASTContext &Context = getContext(); -    CharUnits PointerWidth = -      Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); -    uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); +    uint64_t VTableOffset; +    if (CGM.getItaniumVTableContext().isRelativeLayout()) { +      // Multiply by 4-byte relative offsets. +      VTableOffset = Index * 4; +    } else { +      const ASTContext &Context = getContext(); +      CharUnits PointerWidth = Context.toCharUnitsFromBits( +          Context.getTargetInfo().getPointerWidth(0)); +      VTableOffset = Index * PointerWidth.getQuantity(); +    }      if (UseARMMethodPtrABI) {        // ARM C++ ABI 3.2.1: @@ -1402,8 +1450,19 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,    llvm::Value *Value =        CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl); -  // Load the type info. -  Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL); +  if (CGM.getItaniumVTableContext().isRelativeLayout()) { +    // Load the type info. +    Value = CGF.Builder.CreateBitCast(Value, CGM.Int8PtrTy); +    Value = CGF.Builder.CreateCall( +        CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}), +        {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)}); + +    // Setup to dereference again since this is a proxy we accessed. +    Value = CGF.Builder.CreateBitCast(Value, StdTypeInfoPtrTy->getPointerTo()); +  } else { +    // Load the type info. +    Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL); +  }    return CGF.Builder.CreateAlignedLoad(Value, CGF.getPointerAlign());  } @@ -1459,28 +1518,37 @@ llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF,                                                    Address ThisAddr,                                                    QualType SrcRecordTy,                                                    QualType DestTy) { -  llvm::Type *PtrDiffLTy = -      CGF.ConvertType(CGF.getContext().getPointerDiffType());    llvm::Type *DestLTy = CGF.ConvertType(DestTy); -    auto *ClassDecl =        cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl()); -  // Get the vtable pointer. -  llvm::Value *VTable = CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), -      ClassDecl); +  llvm::Value *OffsetToTop; +  if (CGM.getItaniumVTableContext().isRelativeLayout()) { +    // Get the vtable pointer. +    llvm::Value *VTable = +        CGF.GetVTablePtr(ThisAddr, CGM.Int32Ty->getPointerTo(), ClassDecl); -  // Get the offset-to-top from the vtable. -  llvm::Value *OffsetToTop = -      CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL); -  OffsetToTop = -    CGF.Builder.CreateAlignedLoad(OffsetToTop, CGF.getPointerAlign(), -                                  "offset.to.top"); +    // Get the offset-to-top from the vtable. +    OffsetToTop = +        CGF.Builder.CreateConstInBoundsGEP1_32(/*Type=*/nullptr, VTable, -2U); +    OffsetToTop = CGF.Builder.CreateAlignedLoad( +        OffsetToTop, CharUnits::fromQuantity(4), "offset.to.top"); +  } else { +    llvm::Type *PtrDiffLTy = +        CGF.ConvertType(CGF.getContext().getPointerDiffType()); +    // Get the vtable pointer. +    llvm::Value *VTable = +        CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), ClassDecl); + +    // Get the offset-to-top from the vtable. +    OffsetToTop = CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL); +    OffsetToTop = CGF.Builder.CreateAlignedLoad( +        OffsetToTop, CGF.getPointerAlign(), "offset.to.top"); +  }    // Finally, add the offset to the pointer.    llvm::Value *Value = ThisAddr.getPointer();    Value = CGF.EmitCastToVoidPtr(Value);    Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop); -    return CGF.Builder.CreateBitCast(Value, DestLTy);  } @@ -1501,17 +1569,22 @@ ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,    CharUnits VBaseOffsetOffset =        CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,                                                                 BaseClassDecl); -    llvm::Value *VBaseOffsetPtr =      CGF.Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(),                                     "vbase.offset.ptr"); -  VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr, -                                             CGM.PtrDiffTy->getPointerTo()); - -  llvm::Value *VBaseOffset = -    CGF.Builder.CreateAlignedLoad(VBaseOffsetPtr, CGF.getPointerAlign(), -                                  "vbase.offset"); +  llvm::Value *VBaseOffset; +  if (CGM.getItaniumVTableContext().isRelativeLayout()) { +    VBaseOffsetPtr = +        CGF.Builder.CreateBitCast(VBaseOffsetPtr, CGF.Int32Ty->getPointerTo()); +    VBaseOffset = CGF.Builder.CreateAlignedLoad( +        VBaseOffsetPtr, CharUnits::fromQuantity(4), "vbase.offset"); +  } else { +    VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr, +                                               CGM.PtrDiffTy->getPointerTo()); +    VBaseOffset = CGF.Builder.CreateAlignedLoad( +        VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset"); +  }    return VBaseOffset;  } @@ -1531,7 +1604,7 @@ void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {    }  } -CGCXXABI::AddedStructorArgs +CGCXXABI::AddedStructorArgCounts  ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,                                        SmallVectorImpl<CanQualType> &ArgTys) {    ASTContext &Context = getContext(); @@ -1545,9 +1618,9 @@ ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,        cast<CXXMethodDecl>(GD.getDecl())->getParent()->getNumVBases() != 0) {      ArgTys.insert(ArgTys.begin() + 1,                    Context.getPointerType(Context.VoidPtrTy)); -    return AddedStructorArgs::prefix(1); +    return AddedStructorArgCounts::prefix(1);    } -  return AddedStructorArgs{}; +  return AddedStructorArgCounts{};  }  void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { @@ -1613,9 +1686,9 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {      CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);  } -CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs( +CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(      CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, -    bool ForVirtualBase, bool Delegating, CallArgList &Args) { +    bool ForVirtualBase, bool Delegating) {    if (!NeedsVTTParameter(GlobalDecl(D, Type)))      return AddedStructorArgs{}; @@ -1623,8 +1696,14 @@ CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs(    llvm::Value *VTT =        CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating);    QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); -  Args.insert(Args.begin() + 1, CallArg(RValue::get(VTT), VTTTy)); -  return AddedStructorArgs::prefix(1);  // Added one arg. +  return AddedStructorArgs::prefix({{VTT, VTTTy}}); +} + +llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam( +    CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, +    bool ForVirtualBase, bool Delegating) { +  GlobalDecl GD(DD, Type); +  return CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);  }  void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, @@ -1633,7 +1712,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,                                         bool Delegating, Address This,                                         QualType ThisTy) {    GlobalDecl GD(DD, Type); -  llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating); +  llvm::Value *VTT = +      getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating);    QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);    CGCallee Callee; @@ -1660,10 +1740,11 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,        CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));    // Create and set the initializer. -  ConstantInitBuilder Builder(CGM); -  auto Components = Builder.beginStruct(); -  CGVT.createVTableInitializer(Components, VTLayout, RTTI); -  Components.finishAndSetAsInitializer(VTable); +  ConstantInitBuilder builder(CGM); +  auto components = builder.beginStruct(); +  CGVT.createVTableInitializer(components, VTLayout, RTTI, +                               llvm::GlobalValue::isLocalLinkage(Linkage)); +  components.finishAndSetAsInitializer(VTable);    // Set the correct linkage.    VTable->setLinkage(Linkage); @@ -1687,6 +1768,9 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,    if (!VTable->isDeclarationForLinker())      CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout); + +  if (VTContext.isRelativeLayout() && !VTable->isDSOLocal()) +    CGVT.GenerateRelativeVTableAlias(VTable, VTable->getName());  }  bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField( @@ -1776,7 +1860,9 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,    // Use pointer alignment for the vtable. Otherwise we would align them based    // on the size of the initializer which doesn't make sense as only single    // values are read. -  unsigned PAlign = CGM.getTarget().getPointerAlign(0); +  unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout() +                        ? 32 +                        : CGM.getTarget().getPointerAlign(0);    VTable = CGM.CreateOrReplaceCXXRuntimeVariable(        Name, VTableType, llvm::GlobalValue::ExternalLinkage, @@ -1793,9 +1879,9 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,                                                    Address This,                                                    llvm::Type *Ty,                                                    SourceLocation Loc) { -  Ty = Ty->getPointerTo()->getPointerTo();    auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl()); -  llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent()); +  llvm::Value *VTable = CGF.GetVTablePtr( +      This, Ty->getPointerTo()->getPointerTo(), MethodDecl->getParent());    uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);    llvm::Value *VFunc; @@ -1806,10 +1892,21 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,    } else {      CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc); -    llvm::Value *VFuncPtr = -        CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); -    auto *VFuncLoad = -        CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); +    llvm::Value *VFuncLoad; +    if (CGM.getItaniumVTableContext().isRelativeLayout()) { +      VTable = CGF.Builder.CreateBitCast(VTable, CGM.Int8PtrTy); +      llvm::Value *Load = CGF.Builder.CreateCall( +          CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}), +          {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)}); +      VFuncLoad = CGF.Builder.CreateBitCast(Load, Ty->getPointerTo()); +    } else { +      VTable = +          CGF.Builder.CreateBitCast(VTable, Ty->getPointerTo()->getPointerTo()); +      llvm::Value *VTableSlotPtr = +          CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); +      VFuncLoad = +          CGF.Builder.CreateAlignedLoad(VTableSlotPtr, CGF.getPointerAlign()); +    }      // Add !invariant.load md to virtual function load to indicate that      // function didn't change inside vtable. @@ -1818,11 +1915,14 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,      // the same virtual function loads from the same vtable load, which won't      // happen without enabled devirtualization with -fstrict-vtable-pointers.      if (CGM.getCodeGenOpts().OptimizationLevel > 0 && -        CGM.getCodeGenOpts().StrictVTablePointers) -      VFuncLoad->setMetadata( -          llvm::LLVMContext::MD_invariant_load, -          llvm::MDNode::get(CGM.getLLVMContext(), -                            llvm::ArrayRef<llvm::Metadata *>())); +        CGM.getCodeGenOpts().StrictVTablePointers) { +      if (auto *VFuncLoadInstr = dyn_cast<llvm::Instruction>(VFuncLoad)) { +        VFuncLoadInstr->setMetadata( +            llvm::LLVMContext::MD_invariant_load, +            llvm::MDNode::get(CGM.getLLVMContext(), +                              llvm::ArrayRef<llvm::Metadata *>())); +      } +    }      VFunc = VFuncLoad;    } @@ -1939,21 +2039,28 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,    // Perform the virtual adjustment if we have one.    llvm::Value *ResultPtr;    if (VirtualAdjustment) { -    llvm::Type *PtrDiffTy = -        CGF.ConvertType(CGF.getContext().getPointerDiffType()); -      Address VTablePtrPtr = CGF.Builder.CreateElementBitCast(V, CGF.Int8PtrTy);      llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr); +    llvm::Value *Offset;      llvm::Value *OffsetPtr =          CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment); +    if (CGF.CGM.getItaniumVTableContext().isRelativeLayout()) { +      // Load the adjustment offset from the vtable as a 32-bit int. +      OffsetPtr = +          CGF.Builder.CreateBitCast(OffsetPtr, CGF.Int32Ty->getPointerTo()); +      Offset = +          CGF.Builder.CreateAlignedLoad(OffsetPtr, CharUnits::fromQuantity(4)); +    } else { +      llvm::Type *PtrDiffTy = +          CGF.ConvertType(CGF.getContext().getPointerDiffType()); -    OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo()); - -    // Load the adjustment offset from the vtable. -    llvm::Value *Offset = -      CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign()); +      OffsetPtr = +          CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo()); +      // Load the adjustment offset from the vtable. +      Offset = CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign()); +    }      // Adjust our pointer.      ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getPointer(), Offset);    } else { @@ -2438,7 +2545,7 @@ void CodeGenModule::registerGlobalDtorsWithAtExit() {      std::string GlobalInitFnName =          std::string("__GLOBAL_init_") + llvm::to_string(Priority);      llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); -    llvm::Function *GlobalInitFn = CreateGlobalInitOrDestructFunction( +    llvm::Function *GlobalInitFn = CreateGlobalInitOrCleanUpFunction(          FTy, GlobalInitFnName, getTypes().arrangeNullaryFunction(),          SourceLocation());      ASTContext &Ctx = getContext(); @@ -2592,14 +2699,15 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(      llvm::FunctionType *FTy =          llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);      const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); -    InitFunc = CGM.CreateGlobalInitOrDestructFunction(FTy, "__tls_init", FI, -                                                      SourceLocation(), -                                                      /*TLS=*/true); +    InitFunc = CGM.CreateGlobalInitOrCleanUpFunction(FTy, "__tls_init", FI, +                                                     SourceLocation(), +                                                     /*TLS=*/true);      llvm::GlobalVariable *Guard = new llvm::GlobalVariable(          CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false,          llvm::GlobalVariable::InternalLinkage,          llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard");      Guard->setThreadLocal(true); +    Guard->setThreadLocalMode(CGM.GetDefaultLLVMTLSModel());      CharUnits GuardAlign = CharUnits::One();      Guard->setAlignment(GuardAlign.getAsAlign()); @@ -3008,6 +3116,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {      case BuiltinType::SatUShortFract:      case BuiltinType::SatUFract:      case BuiltinType::SatULongFract: +    case BuiltinType::BFloat16:        return false;      case BuiltinType::Dependent: @@ -3200,9 +3309,11 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {      llvm_unreachable("Pipe types shouldn't get here");    case Type::Builtin: +  case Type::ExtInt:    // GCC treats vector and complex types as fundamental types.    case Type::Vector:    case Type::ExtVector: +  case Type::ConstantMatrix:    case Type::Complex:    case Type::Atomic:    // FIXME: GCC treats block pointers as fundamental types?! @@ -3277,17 +3388,32 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {      break;    } -  llvm::Constant *VTable = -    CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy); +  llvm::Constant *VTable = nullptr; + +  // Check if the alias exists. If it doesn't, then get or create the global. +  if (CGM.getItaniumVTableContext().isRelativeLayout()) +    VTable = CGM.getModule().getNamedAlias(VTableName); +  if (!VTable) +    VTable = CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy); +    CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));    llvm::Type *PtrDiffTy = -    CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); +      CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());    // The vtable address point is 2. -  llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2); -  VTable = -      llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable, Two); +  if (CGM.getItaniumVTableContext().isRelativeLayout()) { +    // The vtable address point is 8 bytes after its start: +    // 4 for the offset to top + 4 for the relative offset to rtti. +    llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8); +    VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy); +    VTable = +        llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight); +  } else { +    llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2); +    VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable, +                                                          Two); +  }    VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);    Fields.push_back(VTable); @@ -3438,6 +3564,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(    case Type::Builtin:    case Type::Vector:    case Type::ExtVector: +  case Type::ConstantMatrix:    case Type::Complex:    case Type::BlockPointer:      // Itanium C++ ABI 2.9.5p4: @@ -3453,7 +3580,10 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(      llvm_unreachable("Undeduced type shouldn't get here");    case Type::Pipe: -    llvm_unreachable("Pipe type shouldn't get here"); +    break; + +  case Type::ExtInt: +    break;    case Type::ConstantArray:    case Type::IncompleteArray: @@ -4401,3 +4531,70 @@ void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,          NormalCleanup, cast<llvm::CatchPadInst>(CGF.CurrentFuncletPad));    ItaniumCXXABI::emitBeginCatch(CGF, C);  } + +/// Register a global destructor as best as we know how. +void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, +                                  llvm::FunctionCallee dtor, +                                  llvm::Constant *addr) { +  if (D.getTLSKind() != VarDecl::TLS_None) +    llvm::report_fatal_error("thread local storage not yet implemented on AIX"); + +  // Create __dtor function for the var decl. +  llvm::Function *dtorStub = CGF.createAtExitStub(D, dtor, addr); + +  // Register above __dtor with atexit(). +  CGF.registerGlobalDtorWithAtExit(dtorStub); + +  // Emit __finalize function to unregister __dtor and (as appropriate) call +  // __dtor. +  emitCXXStermFinalizer(D, dtorStub, addr); +} + +void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub, +                                     llvm::Constant *addr) { +  llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false); +  SmallString<256> FnName; +  { +    llvm::raw_svector_ostream Out(FnName); +    getMangleContext().mangleDynamicStermFinalizer(&D, Out); +  } + +  // Create the finalization action associated with a variable. +  const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); +  llvm::Function *StermFinalizer = CGM.CreateGlobalInitOrCleanUpFunction( +      FTy, FnName.str(), FI, D.getLocation()); + +  CodeGenFunction CGF(CGM); + +  CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, StermFinalizer, FI, +                    FunctionArgList()); + +  // The unatexit subroutine unregisters __dtor functions that were previously +  // registered by the atexit subroutine. If the referenced function is found, +  // the unatexit returns a value of 0, meaning that the cleanup is still +  // pending (and we should call the __dtor function). +  llvm::Value *V = CGF.unregisterGlobalDtorWithUnAtExit(dtorStub); + +  llvm::Value *NeedsDestruct = CGF.Builder.CreateIsNull(V, "needs_destruct"); + +  llvm::BasicBlock *DestructCallBlock = CGF.createBasicBlock("destruct.call"); +  llvm::BasicBlock *EndBlock = CGF.createBasicBlock("destruct.end"); + +  // Check if unatexit returns a value of 0. If it does, jump to +  // DestructCallBlock, otherwise jump to EndBlock directly. +  CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock); + +  CGF.EmitBlock(DestructCallBlock); + +  // Emit the call to dtorStub. +  llvm::CallInst *CI = CGF.Builder.CreateCall(dtorStub); + +  // Make sure the call and the callee agree on calling convention. +  CI->setCallingConv(dtorStub->getCallingConv()); + +  CGF.EmitBlock(EndBlock); + +  CGF.FinishFunction(); + +  CGM.AddCXXStermFinalizerEntry(StermFinalizer); +}  | 
