aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGRecordLayoutBuilder.h
blob: d1a13aa29711ed9c3895fce632e5db12b74db90b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//===--- CGRecordLayoutBuilder.h - Record builder helper --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a helper class used to build CGRecordLayout objects and LLVM types.
//
//===----------------------------------------------------------------------===//

#ifndef CLANG_CODEGEN_CGRECORDLAYOUTBUILDER_H
#define CLANG_CODEGEN_CGRECORDLAYOUTBUILDER_H

#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
#include <vector>

namespace llvm {
  class Type;
}

namespace clang {
  class FieldDecl;
  class RecordDecl;

namespace CodeGen {
  class CGRecordLayout;
  class CodeGenTypes;

class CGRecordLayoutBuilder {
  CodeGenTypes &Types;

  /// Packed - Whether the resulting LLVM struct will be packed or not.
  bool Packed;

  /// ContainsMemberPointer - Whether one of the fields is a member pointer
  /// or is a struct that contains a member pointer.
  bool ContainsMemberPointer;

  /// Alignment - Contains the alignment of the RecordDecl.
  unsigned Alignment;

  /// AlignmentAsLLVMStruct - Will contain the maximum alignment of all the
  /// LLVM types.
  unsigned AlignmentAsLLVMStruct;

  /// 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;

  /// NextFieldOffsetInBytes - Holds the next field offset in bytes.
  uint64_t NextFieldOffsetInBytes;

  /// FieldTypes - Holds the LLVM types that the struct is created from.
  std::vector<const llvm::Type *> FieldTypes;

  /// LLVMFieldInfo - Holds a field and its corresponding LLVM field number.
  typedef std::pair<const FieldDecl *, unsigned> LLVMFieldInfo;
  llvm::SmallVector<LLVMFieldInfo, 16> LLVMFields;

  /// LLVMBitFieldInfo - Holds location and size information about a bit field.
  struct LLVMBitFieldInfo {
    LLVMBitFieldInfo(const FieldDecl *FD, unsigned FieldNo, unsigned Start,
                     unsigned Size)
      : FD(FD), FieldNo(FieldNo), Start(Start), Size(Size) { }

    const FieldDecl *FD;

    unsigned FieldNo;
    unsigned Start;
    unsigned Size;
  };
  llvm::SmallVector<LLVMBitFieldInfo, 16> LLVMBitFields;

  CGRecordLayoutBuilder(CodeGenTypes &Types)
    : Types(Types), Packed(false), ContainsMemberPointer(false)
    , Alignment(0), AlignmentAsLLVMStruct(1)
    , BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { }

  /// Layout - Will layout a RecordDecl.
  void Layout(const RecordDecl *D);

  /// 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);

  /// LayoutField - layout a single field. Returns false if the operation failed
  /// because the current struct is not packed.
  bool LayoutField(const FieldDecl *D, uint64_t FieldOffset);

  /// LayoutBitField - layout a single bit field.
  void LayoutBitField(const FieldDecl *D, uint64_t FieldOffset);

  /// AppendField - Appends a field with the given offset and type.
  void AppendField(uint64_t FieldOffsetInBytes, const llvm::Type *FieldTy);

  /// AppendPadding - Appends enough padding bytes so that the total struct
  /// size matches the alignment of the passed in type.
  void AppendPadding(uint64_t FieldOffsetInBytes, const llvm::Type *FieldTy);

  /// AppendPadding - Appends enough padding bytes so that the total
  /// struct size is a multiple of the field alignment.
  void AppendPadding(uint64_t FieldOffsetInBytes, unsigned FieldAlignment);

  /// AppendBytes - Append a given number of bytes to the record.
  void AppendBytes(uint64_t NumBytes);

  /// AppendTailPadding - Append enough tail padding so that the type will have
  /// the passed size.
  void AppendTailPadding(uint64_t RecordSize);

  unsigned getTypeAlignment(const llvm::Type *Ty) const;
  uint64_t getTypeSizeInBytes(const llvm::Type *Ty) const;

  /// CheckForMemberPointer - Check if the field contains a member pointer.
  void CheckForMemberPointer(const FieldDecl *FD);

public:
  /// ComputeLayout - Return the right record layout for a given record decl.
  static CGRecordLayout *ComputeLayout(CodeGenTypes &Types,
                                       const RecordDecl *D);
};

} // end namespace CodeGen
} // end namespace clang


#endif