summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/ABIInfo.h
blob: 2853bc80a5d43536eaaa9e143230bea77fb7ea6f (plain)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
//===----- ABIInfo.h - ABI information access & encapsulation ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef CLANG_CODEGEN_ABIINFO_H
#define CLANG_CODEGEN_ABIINFO_H

#include "clang/AST/Type.h"
#include "llvm/Type.h"

namespace llvm {
  class Value;
  class LLVMContext;
  class TargetData;
}

namespace clang {
  class ASTContext;

  namespace CodeGen {
    class CGFunctionInfo;
    class CodeGenFunction;
    class CodeGenTypes;
  }

  // FIXME: All of this stuff should be part of the target interface
  // somehow. It is currently here because it is not clear how to factor
  // the targets to support this, since the Targets currently live in a
  // layer below types n'stuff.

  /// ABIArgInfo - Helper class to encapsulate information about how a
  /// specific C type should be passed to or returned from a function.
  class ABIArgInfo {
  public:
    enum Kind {
      /// Direct - Pass the argument directly using the normal converted LLVM
      /// type, or by coercing to another specified type stored in
      /// 'CoerceToType').  If an offset is specified (in UIntData), then the
      /// argument passed is offset by some number of bytes in the memory
      /// representation. A dummy argument is emitted before the real argument
      /// if the specified type stored in "PaddingType" is not zero.
      Direct,

      /// Extend - Valid only for integer argument types. Same as 'direct'
      /// but also emit a zero/sign extension attribute.
      Extend,

      /// Indirect - Pass the argument indirectly via a hidden pointer
      /// with the specified alignment (0 indicates default alignment).
      Indirect,

      /// Ignore - Ignore the argument (treat as void). Useful for void and
      /// empty structs.
      Ignore,

      /// Expand - Only valid for aggregate argument types. The structure should
      /// be expanded into consecutive arguments for its constituent fields.
      /// Currently expand is only allowed on structures whose fields
      /// are all scalar types or are themselves expandable types.
      Expand,

      KindFirst=Direct, KindLast=Expand
    };

  private:
    Kind TheKind;
    llvm::Type *TypeData;
    llvm::Type *PaddingType; // Currently allowed only for Direct.
    unsigned UIntData;
    bool BoolData0;
    bool BoolData1;

    ABIArgInfo(Kind K, llvm::Type *TD=0, unsigned UI=0,
               bool B0 = false, bool B1 = false, llvm::Type* P = 0)
      : TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0),
        BoolData1(B1) {}

  public:
    ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}

    static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0,
                                llvm::Type *Padding = 0) {
      return ABIArgInfo(Direct, T, Offset, false, false, Padding);
    }
    static ABIArgInfo getExtend(llvm::Type *T = 0) {
      return ABIArgInfo(Extend, T, 0);
    }
    static ABIArgInfo getIgnore() {
      return ABIArgInfo(Ignore);
    }
    static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
                                  , bool Realign = false) {
      return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign);
    }
    static ABIArgInfo getExpand() {
      return ABIArgInfo(Expand);
    }

    Kind getKind() const { return TheKind; }
    bool isDirect() const { return TheKind == Direct; }
    bool isExtend() const { return TheKind == Extend; }
    bool isIgnore() const { return TheKind == Ignore; }
    bool isIndirect() const { return TheKind == Indirect; }
    bool isExpand() const { return TheKind == Expand; }

    bool canHaveCoerceToType() const {
      return TheKind == Direct || TheKind == Extend;
    }

    // Direct/Extend accessors
    unsigned getDirectOffset() const {
      assert((isDirect() || isExtend()) && "Not a direct or extend kind");
      return UIntData;
    }

    llvm::Type *getPaddingType() const {
      return PaddingType;
    }

    llvm::Type *getCoerceToType() const {
      assert(canHaveCoerceToType() && "Invalid kind!");
      return TypeData;
    }

    void setCoerceToType(llvm::Type *T) {
      assert(canHaveCoerceToType() && "Invalid kind!");
      TypeData = T;
    }

    // Indirect accessors
    unsigned getIndirectAlign() const {
      assert(TheKind == Indirect && "Invalid kind!");
      return UIntData;
    }

    bool getIndirectByVal() const {
      assert(TheKind == Indirect && "Invalid kind!");
      return BoolData0;
    }

    bool getIndirectRealign() const {
      assert(TheKind == Indirect && "Invalid kind!");
      return BoolData1;
    }

    void dump() const;
  };

  /// ABIInfo - Target specific hooks for defining how a type should be
  /// passed or returned from functions.
  class ABIInfo {
  public:
    CodeGen::CodeGenTypes &CGT;

    ABIInfo(CodeGen::CodeGenTypes &cgt) : CGT(cgt) {}
    virtual ~ABIInfo();

    ASTContext &getContext() const;
    llvm::LLVMContext &getVMContext() const;
    const llvm::TargetData &getTargetData() const;

    virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;

    /// EmitVAArg - Emit the target dependent code to load a value of
    /// \arg Ty from the va_list pointed to by \arg VAListAddr.

    // FIXME: This is a gaping layering violation if we wanted to drop
    // the ABI information any lower than CodeGen. Of course, for
    // VAArg handling it has to be at this level; there is no way to
    // abstract this out.
    virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
                                   CodeGen::CodeGenFunction &CGF) const = 0;
  };
}  // end namespace clang

#endif