clang API Documentation

CGVTT.cpp
Go to the documentation of this file.
00001 //===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This contains code dealing with C++ code generation of VTTs (vtable tables).
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "CodeGenModule.h"
00015 #include "CGCXXABI.h"
00016 #include "clang/AST/RecordLayout.h"
00017 #include "clang/AST/VTTBuilder.h"
00018 using namespace clang;
00019 using namespace CodeGen;
00020 
00021 static llvm::Constant *
00022 GetAddrOfVTTVTable(CodeGenVTables &CGVT, const CXXRecordDecl *MostDerivedClass,
00023                    const VTTVTable &VTable,
00024                    llvm::GlobalVariable::LinkageTypes Linkage,
00025                    llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) {
00026   if (VTable.getBase() == MostDerivedClass) {
00027     assert(VTable.getBaseOffset().isZero() &&
00028            "Most derived class vtable must have a zero offset!");
00029     // This is a regular vtable.
00030     return CGVT.GetAddrOfVTable(MostDerivedClass);
00031   }
00032   
00033   return CGVT.GenerateConstructionVTable(MostDerivedClass, 
00034                                          VTable.getBaseSubobject(),
00035                                          VTable.isVirtual(),
00036                                          Linkage,
00037                                          AddressPoints);
00038 }
00039 
00040 void
00041 CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
00042                                   llvm::GlobalVariable::LinkageTypes Linkage,
00043                                   const CXXRecordDecl *RD) {
00044   VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true);
00045 
00046   llvm::Type *Int8PtrTy = CGM.Int8PtrTy, *Int64Ty = CGM.Int64Ty;
00047   llvm::ArrayType *ArrayType = 
00048     llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
00049   
00050   SmallVector<llvm::Constant *, 8> VTables;
00051   SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints;
00052   for (const VTTVTable *i = Builder.getVTTVTables().begin(),
00053                        *e = Builder.getVTTVTables().end(); i != e; ++i) {
00054     VTableAddressPoints.push_back(VTableAddressPointsMapTy());
00055     VTables.push_back(GetAddrOfVTTVTable(*this, RD, *i, Linkage,
00056                                          VTableAddressPoints.back()));
00057   }
00058 
00059   SmallVector<llvm::Constant *, 8> VTTComponents;
00060   for (const VTTComponent *i = Builder.getVTTComponents().begin(),
00061                           *e = Builder.getVTTComponents().end(); i != e; ++i) {
00062     const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex];
00063     llvm::Constant *VTable = VTables[i->VTableIndex];
00064     uint64_t AddressPoint;
00065     if (VTTVT.getBase() == RD) {
00066       // Just get the address point for the regular vtable.
00067       AddressPoint = VTContext.getVTableLayout(RD)
00068                               .getAddressPoint(i->VTableBase);
00069       assert(AddressPoint != 0 && "Did not find vtable address point!");
00070     } else {
00071       AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);
00072       assert(AddressPoint != 0 && "Did not find ctor vtable address point!");
00073     }
00074 
00075      llvm::Value *Idxs[] = {
00076        llvm::ConstantInt::get(Int64Ty, 0),
00077        llvm::ConstantInt::get(Int64Ty, AddressPoint)
00078      };
00079 
00080      llvm::Constant *Init = 
00081        llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs);
00082 
00083      Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
00084 
00085      VTTComponents.push_back(Init);
00086   }
00087 
00088   llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents);
00089 
00090   VTT->setInitializer(Init);
00091 
00092   // Set the correct linkage.
00093   VTT->setLinkage(Linkage);
00094 
00095   // Set the right visibility.
00096   CGM.setTypeVisibility(VTT, RD, CodeGenModule::TVK_ForVTT);
00097 }
00098 
00099 llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
00100   assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT");
00101 
00102   SmallString<256> OutName;
00103   llvm::raw_svector_ostream Out(OutName);
00104   CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, Out);
00105   Out.flush();
00106   StringRef Name = OutName.str();
00107 
00108   // This will also defer the definition of the VTT.
00109   (void) GetAddrOfVTable(RD);
00110 
00111   VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
00112 
00113   llvm::ArrayType *ArrayType = 
00114     llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size());
00115 
00116   llvm::GlobalVariable *GV =
00117     CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, 
00118                                           llvm::GlobalValue::ExternalLinkage);
00119   GV->setUnnamedAddr(true);
00120   return GV;
00121 }
00122 
00123 bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
00124   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
00125   
00126   // We don't have any virtual bases, just return early.
00127   if (!MD->getParent()->getNumVBases())
00128     return false;
00129   
00130   // Check if we have a base constructor.
00131   if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
00132     return true;
00133 
00134   // Check if we have a base destructor.
00135   if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
00136     return true;
00137   
00138   return false;
00139 }
00140 
00141 uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, 
00142                                         BaseSubobject Base) {
00143   BaseSubobjectPairTy ClassSubobjectPair(RD, Base);
00144 
00145   SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair);
00146   if (I != SubVTTIndicies.end())
00147     return I->second;
00148   
00149   VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
00150 
00151   for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
00152        Builder.getSubVTTIndicies().begin(), 
00153        E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
00154     // Insert all indices.
00155     BaseSubobjectPairTy ClassSubobjectPair(RD, I->first);
00156     
00157     SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second));
00158   }
00159     
00160   I = SubVTTIndicies.find(ClassSubobjectPair);
00161   assert(I != SubVTTIndicies.end() && "Did not find index!");
00162   
00163   return I->second;
00164 }
00165 
00166 uint64_t 
00167 CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
00168                                                 BaseSubobject Base) {
00169   SecondaryVirtualPointerIndicesMapTy::iterator I =
00170     SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
00171 
00172   if (I != SecondaryVirtualPointerIndices.end())
00173     return I->second;
00174 
00175   VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
00176 
00177   // Insert all secondary vpointer indices.
00178   for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = 
00179        Builder.getSecondaryVirtualPointerIndices().begin(),
00180        E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) {
00181     std::pair<const CXXRecordDecl *, BaseSubobject> Pair =
00182       std::make_pair(RD, I->first);
00183     
00184     SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second));
00185   }
00186 
00187   I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
00188   assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!");
00189   
00190   return I->second;
00191 }
00192