aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/DeclCXX.cpp4
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp2
-rw-r--r--lib/CodeGen/CGCXX.cpp57
-rw-r--r--lib/CodeGen/CodeGenFunction.h2
-rw-r--r--lib/CodeGen/CodeGenModule.h2
-rw-r--r--lib/CodeGen/Mangle.cpp20
-rw-r--r--lib/CodeGen/Mangle.h2
7 files changed, 76 insertions, 13 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 11c7e6dfc2..cc481be6ba 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -377,6 +377,8 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
if (ClassTemplateDecl *TD = getParent()->getDescribedClassTemplate())
ClassTy = TD->getInjectedClassNameType(C);
else
+ // FIXME: What is the design on getTagDeclType when it requires casting
+ // away const? mutable?
ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
return C.getPointerType(ClassTy);
@@ -652,7 +654,7 @@ CXXConstructorDecl::setBaseOrMemberInitializers(
AllToInit.push_back(Member);
}
}
-
+
NumInitializers = AllToInit.size();
if (NumInitializers > 0) {
NumBaseOrMemberInitializers = NumInitializers;
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 41bd521331..901d5a5b26 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -27,7 +27,7 @@ ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
if (RD->isPolymorphic() || RD->getNumVBases())
{
- assert (RD->getNumBases() == 0 && "no polymorphic inheritance yet");
+ // assert (RD->getNumBases() == 0 && "no polymorphic inheritance yet");
int AS = 0;
UpdateAlignment(Ctx.Target.getPointerAlign(AS));
Size += Ctx.Target.getPointerWidth(AS);
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 4d48f0801f..88d36a2c00 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -107,8 +107,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {
const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
- // FIXME: It isn't just virtual as written, but all virtual functions.
- if (MD->isVirtualAsWritten()) {
+ if (MD->isVirtual()) {
ErrorUnsupported(CE, "virtual dispatch");
}
@@ -491,21 +490,54 @@ const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
return UniqueMangledName(Name.begin(), Name.end());
}
+llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
+ const llvm::FunctionType *FTy;
+ FTy = llvm::FunctionType::get(llvm::Type::VoidTy,
+ std::vector<const llvm::Type*>(), false);
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ QualType ClassTy;
+ // FIXME: What is the design on getTagDeclType when it requires casting
+ // away const? mutable?
+ ClassTy = getContext().getTagDeclType(const_cast<CXXRecordDecl*>(RD));
+ mangleCXXVtable(ClassTy, getContext(), Out);
+ const char *Name = OutName.c_str();
+ llvm::Value *vtable = CGM.CreateRuntimeFunction(FTy, Name);
+ llvm::SmallVector<CXXMethodDecl *,32> methods;
+ typedef CXXRecordDecl::method_iterator meth_iter;
+ for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
+ ++mi) {
+ if (mi->isVirtual())
+ methods.push_back(*mi);
+ }
+
+ llvm::Type *Ptr8Ty;
+ Ptr8Ty = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
+ vtable = Builder.CreateBitCast(vtable, Ptr8Ty);
+ // FIXME: finish layout for virtual bases and fix for 32-bit
+ int64_t offset = 16;
+ vtable = Builder.CreateGEP(vtable,
+ llvm::ConstantInt::get(llvm::Type::Int64Ty,
+ offset));
+ return vtable;
+}
+
/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
- assert(!ClassDecl->isPolymorphic()
- && "FIXME: virtual table initialization unsupported");
assert(ClassDecl->getNumVBases() == 0
&& "FIXME: virtual base initialization unsupported");
+ llvm::Value *LoadOfThis = 0;
+
for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
E = CD->init_end();
B != E; ++B) {
CXXBaseOrMemberInitializer *Member = (*B);
if (Member->isBaseInitializer()) {
- llvm::Value *LoadOfThis = LoadCXXThis();
+ LoadOfThis = LoadCXXThis();
Type *BaseType = Member->getBaseClass();
CXXRecordDecl *BaseClassDecl =
cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
@@ -522,7 +554,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
assert(!getContext().getAsArrayType(FieldType)
&& "FIXME. Field arrays initialization unsupported");
- llvm::Value *LoadOfThis = LoadCXXThis();
+ LoadOfThis = LoadCXXThis();
LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
if (FieldType->getAs<RecordType>()) {
@@ -544,6 +576,19 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
EmitStoreThroughLValue(RValue::get(RHS), LHS, FieldType);
}
}
+
+ // Initialize the vtable pointer
+ if (ClassDecl->isPolymorphic() || ClassDecl->getNumVBases()) {
+ if (!LoadOfThis)
+ LoadOfThis = LoadCXXThis();
+ llvm::Value *VtableField;
+ llvm::Type *Ptr8Ty, *PtrPtr8Ty;
+ Ptr8Ty = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
+ PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0);
+ VtableField = Builder.CreateBitCast(LoadOfThis, PtrPtr8Ty);
+ llvm::Value *vtable = GenerateVtable(ClassDecl);
+ Builder.CreateStore(vtable, VtableField);
+ }
}
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 4f8a14af14..5661343c13 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -358,6 +358,8 @@ public:
/// legal to call this function even if there is no current insertion point.
void FinishFunction(SourceLocation EndLoc=SourceLocation());
+ llvm::Value *GenerateVtable(const CXXRecordDecl *RD);
+
void EmitCtorPrologue(const CXXConstructorDecl *CD);
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 46caaaf3c1..c7437d18ef 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -373,7 +373,7 @@ public:
CXXDtorType Type);
void EmitTentativeDefinition(const VarDecl *D);
-
+
enum GVALinkage {
GVA_Internal,
GVA_C99Inline,
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 9e389040b8..36ee2a4222 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -41,6 +41,7 @@ namespace {
bool mangle(const NamedDecl *D);
void mangleGuardVariable(const VarDecl *D);
+ void mangleCXXVtable(QualType Type);
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type);
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type);
@@ -158,10 +159,16 @@ void CXXNameMangler::mangleCXXDtor(const CXXDestructorDecl *D,
mangle(D);
}
+void CXXNameMangler::mangleCXXVtable(QualType T) {
+ // <special-name> ::= TV <type> # virtual table
+ Out << "_ZTV";
+ mangleType(T);
+}
+
void CXXNameMangler::mangleGuardVariable(const VarDecl *D)
{
// <special-name> ::= GV <object name> # Guard variable for one-time
- // # initialization
+ // # initialization
Out << "_ZGV";
mangleName(D);
@@ -807,7 +814,12 @@ namespace clang {
os.flush();
}
-
-
-}
+ void mangleCXXVtable(QualType Type, ASTContext &Context,
+ llvm::raw_ostream &os) {
+ CXXNameMangler Mangler(Context, os);
+ Mangler.mangleCXXVtable(Type);
+
+ os.flush();
+ }
+}
diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h
index 77cbd97751..1a5ca63c50 100644
--- a/lib/CodeGen/Mangle.h
+++ b/lib/CodeGen/Mangle.h
@@ -19,6 +19,7 @@
#define LLVM_CLANG_CODEGEN_MANGLE_H
#include "CGCXX.h"
+#include "clang/AST/Type.h"
namespace llvm {
class raw_ostream;
@@ -35,6 +36,7 @@ namespace clang {
llvm::raw_ostream &os);
void mangleGuardVariable(const VarDecl *D, ASTContext &Context,
llvm::raw_ostream &os);
+ void mangleCXXVtable(QualType T, ASTContext &Context, llvm::raw_ostream &os);
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
ASTContext &Context, llvm::raw_ostream &os);
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,