//===--- CGRecordLayoutBuilder.cpp - CGRecordLayout builder ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Builder implementation for CGRecordLayout objects.
//
//===----------------------------------------------------------------------===//
#include "CGRecordLayout.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "CodeGenTypes.h"
#include "CGCXXABI.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Type.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
namespace {
class CGRecordLayoutBuilder {
public:
/// FieldTypes - Holds the LLVM types that the struct is created from.
///
SmallVector<llvm::Type *, 16> FieldTypes;
/// BaseSubobjectType - Holds the LLVM type for the non-virtual part
/// of the struct. For example, consider:
///
/// struct A { int i; };
/// struct B { void *v; };
/// struct C : virtual A, B { };
///
/// The LLVM type of C will be
/// %struct.C = type { i32 (...)**, %struct.A, i32, %struct.B }
///
/// And the LLVM type of the non-virtual base struct will be
/// %struct.C.base = type { i32 (...)**, %struct.A, i32 }
///
/// This only gets initialized if the base subobject type is
/// different from the complete-object type.
llvm::StructType *BaseSubobjectType;
/// FieldInfo - Holds a field and its corresponding LLVM field number.
llvm::DenseMap<const FieldDecl *, unsigned> Fields;
/// BitFieldInfo - Holds location and size information about a bit field.
llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases;
/// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are
/// primary base classes for some other direct or indirect base class.
CXXIndirectPrimaryBaseSet IndirectPrimaryBases;
/// LaidOutVirtualBases - A set of all laid out virtual bases, used to avoid
/// avoid laying out virtual bases more than once.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> LaidOutVirtualBases;
/// IsZeroInitializable - Whether this struct can be C++
/// zero-initialized with an LLVM zeroinitializer.
bool IsZeroInitializable;
bool IsZeroInitializableAsBase;
/// Packed - Whether the resulting LLVM struct will be packed or not.
bool Packed;
/// IsMsStruct - Whether ms_struct is in effect or not
bool IsMsStruct;
private:
CodeGenTypes &Types;
/// LastLaidOutBaseInfo - Contains the offset and non-virtual size of the
/// last base laid out. Used so that we can replace the last laid out base
/// type with an i8 array if needed.
struct LastLaidOutBaseInfo {
CharUnits Offset;
CharUnits NonVirtualSize;
bool isValid() const { return !NonVirtualSize.isZero(); }
void invalidate() { NonVirtualSize = CharUnits::Zero(); }
} LastLaidOutBase;
/// Alignment - Contains the alignment of the RecordDecl.
CharUnits Alignment;
/// BitsAvailableInLastField - If a bit field spans only part of a LLVM field,
/// this will have the number of bits still available in the field.
char BitsAvailableInLastField;
/// NextFieldOffset - Holds the next field offset.
CharUnits NextFieldOffset;
/// LayoutUnionField - Will layout a field in an union and return the type
/// that the field will have.
llvm::Type *LayoutUnionField(const FieldDecl *Field,
const ASTRecordLayout &Layout);
/// LayoutUnion - Will layout a union RecordDecl.
void LayoutUnion(const RecordDecl *D);
/// LayoutField - try to layout all fields in the record decl.
/// Returns false if the operation failed because the struct is not packed.
bool LayoutFields(const RecordDecl *D);
/// Layout a single base, virtual or non-virtual
bool LayoutBase(const CXXRecordDecl *base,
const CGRecordLayout &baseLayout,
CharUnits baseOffset);
/// LayoutVirtualBase - layout a single virtual base.
bool LayoutVirtualBase(const CXXRecordDecl *base,
CharUnits baseOffset);
/// LayoutVirtualBases - layout the virtual bases of a record decl.
bool LayoutVirtualBases(const CXXRecordDecl *RD,
const ASTRecordLayout &Layout