"llvm/lib/Target/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "5c91a5e7473c14d6ea3ad16dfcf4a80e991a53f8"
Newer
Older
Anders Carlsson
committed
//===--- CGClass.cpp - Emit LLVM Code for C++ classes ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ code generation of classes
//
//===----------------------------------------------------------------------===//
#include "CGBlocks.h"
Devang Patel
committed
#include "CGDebugInfo.h"
Anders Carlsson
committed
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/StmtCXX.h"
Devang Patel
committed
#include "clang/Frontend/CodeGenOptions.h"
Anders Carlsson
committed
using namespace clang;
using namespace CodeGen;
static CharUnits
Anders Carlsson
committed
ComputeNonVirtualBaseClassOffset(ASTContext &Context,
const CXXRecordDecl *DerivedClass,
CastExpr::path_const_iterator Start,
CastExpr::path_const_iterator End) {
CharUnits Offset = CharUnits::Zero();
Anders Carlsson
committed
const CXXRecordDecl *RD = DerivedClass;
for (CastExpr::path_const_iterator I = Start; I != End; ++I) {
Anders Carlsson
committed
const CXXBaseSpecifier *Base = *I;
assert(!Base->isVirtual() && "Should not see virtual bases here!");
// Get the layout.
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
// Add the offset.
Offset += Layout.getBaseClassOffset(BaseDecl);
Anders Carlsson
committed
RD = BaseDecl;
}
return Offset;
Anders Carlsson
committed
}
llvm::Constant *
CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd) {
assert(PathBegin != PathEnd && "Base path should not be empty!");
CharUnits Offset =
ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
PathBegin, PathEnd);
if (Offset.isZero())
return 0;
Types.ConvertType(getContext().getPointerDiffType());
return llvm::ConstantInt::get(PtrDiffTy, Offset.getQuantity());
Anders Carlsson
committed
}
Anders Carlsson
committed
/// Gets the address of a direct base class within a complete object.
/// This should only be used for (1) non-virtual bases or (2) virtual bases
/// when the type is known to be complete (e.g. in complete destructors).
///
/// The object pointed to by 'This' is assumed to be non-null.
llvm::Value *
Anders Carlsson
committed
CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(llvm::Value *This,
const CXXRecordDecl *Derived,
const CXXRecordDecl *Base,
bool BaseIsVirtual) {
// 'this' must be a pointer (in some address space) to Derived.
assert(This->getType()->isPointerTy() &&
cast<llvm::PointerType>(This->getType())->getElementType()
== ConvertType(Derived));
// Compute the offset of the virtual base.
CharUnits Offset;
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived);
Anders Carlsson
committed
if (BaseIsVirtual)
Offset = Layout.getVBaseClassOffset(Base);
else
Offset = Layout.getBaseClassOffset(Base);
// Shift and cast down to the base type.
// TODO: for complete types, this should be possible with a GEP.
llvm::Value *V = This;
if (Offset.isPositive()) {
V = Builder.CreateBitCast(V, Int8PtrTy);
V = Builder.CreateConstInBoundsGEP1_64(V, Offset.getQuantity());
}
V = Builder.CreateBitCast(V, ConvertType(Base)->getPointerTo());
return V;
Anders Carlsson
committed
static llvm::Value *
ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ptr,
CharUnits nonVirtualOffset,
llvm::Value *virtualOffset) {
// Assert that we have something to do.
assert(!nonVirtualOffset.isZero() || virtualOffset != 0);
// Compute the offset from the static and dynamic components.
llvm::Value *baseOffset;
if (!nonVirtualOffset.isZero()) {
baseOffset = llvm::ConstantInt::get(CGF.PtrDiffTy,
nonVirtualOffset.getQuantity());
if (virtualOffset) {
baseOffset = CGF.Builder.CreateAdd(virtualOffset, baseOffset);
}
} else {
baseOffset = virtualOffset;
}
Anders Carlsson
committed
// Apply the base offset.
ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8PtrTy);
ptr = CGF.Builder.CreateInBoundsGEP(ptr, baseOffset, "add.ptr");
return ptr;
Anders Carlsson
committed
}
Anders Carlsson
committed
llvm::Value *
CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
Anders Carlsson
committed
const CXXRecordDecl *Derived,
CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd,
Anders Carlsson
committed
bool NullCheckValue) {
assert(PathBegin != PathEnd && "Base path should not be empty!");
Anders Carlsson
committed
CastExpr::path_const_iterator Start = PathBegin;
Anders Carlsson
committed
const CXXRecordDecl *VBase = 0;
// Sema has done some convenient canonicalization here: if the
// access path involved any virtual steps, the conversion path will
// *start* with a step down to the correct virtual base subobject,
// and hence will not require any further steps.
Anders Carlsson
committed
if ((*Start)->isVirtual()) {
VBase =
cast<CXXRecordDecl>((*Start)->getType()->getAs<RecordType>()->getDecl());
++Start;
}
// Compute the static offset of the ultimate destination within its
// allocating subobject (the virtual base, if there is one, or else
// the "complete" object that we see).
CharUnits NonVirtualOffset =
Anders Carlsson
committed
ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived,
Start, PathEnd);
Anders Carlsson
committed
// If there's a virtual step, we can sometimes "devirtualize" it.
// For now, that's limited to when the derived type is final.
// TODO: "devirtualize" this for accesses to known-complete objects.
if (VBase && Derived->hasAttr<FinalAttr>()) {
const ASTRecordLayout &layout = getContext().getASTRecordLayout(Derived);
CharUnits vBaseOffset = layout.getVBaseClassOffset(VBase);
NonVirtualOffset += vBaseOffset;
VBase = 0; // we no longer have a virtual step
}
Anders Carlsson
committed
// Get the base pointer type.
ConvertType((PathEnd[-1])->getType())->getPointerTo();
// If the static offset is zero and we don't have a virtual step,
// just do a bitcast; null checks are unnecessary.
if (NonVirtualOffset.isZero() && !VBase) {
Anders Carlsson
committed
return Builder.CreateBitCast(Value, BasePtrTy);
}
llvm::BasicBlock *origBB = 0;
llvm::BasicBlock *endBB = 0;
Anders Carlsson
committed
// Skip over the offset (and the vtable load) if we're supposed to
// null-check the pointer.
Anders Carlsson
committed
if (NullCheckValue) {
origBB = Builder.GetInsertBlock();
llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull");
endBB = createBasicBlock("cast.end");
Anders Carlsson
committed
llvm::Value *isNull = Builder.CreateIsNull(Value);
Builder.CreateCondBr(isNull, endBB, notNullBB);
EmitBlock(notNullBB);
Anders Carlsson
committed
}
// Compute the virtual offset.
Anders Carlsson
committed
llvm::Value *VirtualOffset = 0;
Anders Carlsson
committed
if (VBase) {
VirtualOffset = GetVirtualBaseClassOffset(Value, Derived, VBase);
Anders Carlsson
committed
}
Loading
Loading full blame...