1249259Sdim//===-- llvm/InlineAsm.h - Class to represent inline asm strings-*- C++ -*-===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This class represents the inline asm strings, which are Value*'s that are
11249259Sdim// used as the callee operand of call instructions.  InlineAsm's are uniqued
12249259Sdim// like constants, and created via InlineAsm::get(...).
13249259Sdim//
14249259Sdim//===----------------------------------------------------------------------===//
15249259Sdim
16249259Sdim#ifndef LLVM_IR_INLINEASM_H
17249259Sdim#define LLVM_IR_INLINEASM_H
18249259Sdim
19249259Sdim#include "llvm/ADT/StringRef.h"
20249259Sdim#include "llvm/IR/Value.h"
21249259Sdim#include <vector>
22249259Sdim
23249259Sdimnamespace llvm {
24249259Sdim
25249259Sdimclass PointerType;
26249259Sdimclass FunctionType;
27249259Sdimclass Module;
28249259Sdimstruct InlineAsmKeyType;
29249259Sdimtemplate<class ValType, class ValRefType, class TypeClass, class ConstantClass,
30249259Sdim         bool HasLargeKey>
31249259Sdimclass ConstantUniqueMap;
32249259Sdimtemplate<class ConstantClass, class TypeClass, class ValType>
33249259Sdimstruct ConstantCreator;
34249259Sdim
35249259Sdimclass InlineAsm : public Value {
36249259Sdimpublic:
37249259Sdim  enum AsmDialect {
38249259Sdim    AD_ATT,
39249259Sdim    AD_Intel
40249259Sdim  };
41249259Sdim
42249259Sdimprivate:
43249259Sdim  friend struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType>;
44249259Sdim  friend class ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&,
45249259Sdim                                 PointerType, InlineAsm, false>;
46249259Sdim
47249259Sdim  InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION;
48249259Sdim  void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION;
49249259Sdim
50249259Sdim  std::string AsmString, Constraints;
51249259Sdim  bool HasSideEffects;
52249259Sdim  bool IsAlignStack;
53249259Sdim  AsmDialect Dialect;
54249259Sdim
55249259Sdim  InlineAsm(PointerType *Ty, const std::string &AsmString,
56249259Sdim            const std::string &Constraints, bool hasSideEffects,
57249259Sdim            bool isAlignStack, AsmDialect asmDialect);
58249259Sdim  virtual ~InlineAsm();
59249259Sdim
60249259Sdim  /// When the ConstantUniqueMap merges two types and makes two InlineAsms
61249259Sdim  /// identical, it destroys one of them with this method.
62249259Sdim  void destroyConstant();
63249259Sdimpublic:
64249259Sdim
65249259Sdim  /// InlineAsm::get - Return the specified uniqued inline asm string.
66249259Sdim  ///
67249259Sdim  static InlineAsm *get(FunctionType *Ty, StringRef AsmString,
68249259Sdim                        StringRef Constraints, bool hasSideEffects,
69249259Sdim                        bool isAlignStack = false,
70249259Sdim                        AsmDialect asmDialect = AD_ATT);
71249259Sdim
72249259Sdim  bool hasSideEffects() const { return HasSideEffects; }
73249259Sdim  bool isAlignStack() const { return IsAlignStack; }
74249259Sdim  AsmDialect getDialect() const { return Dialect; }
75249259Sdim
76249259Sdim  /// getType - InlineAsm's are always pointers.
77249259Sdim  ///
78249259Sdim  PointerType *getType() const {
79249259Sdim    return reinterpret_cast<PointerType*>(Value::getType());
80249259Sdim  }
81249259Sdim
82249259Sdim  /// getFunctionType - InlineAsm's are always pointers to functions.
83249259Sdim  ///
84249259Sdim  FunctionType *getFunctionType() const;
85249259Sdim
86249259Sdim  const std::string &getAsmString() const { return AsmString; }
87249259Sdim  const std::string &getConstraintString() const { return Constraints; }
88249259Sdim
89249259Sdim  /// Verify - This static method can be used by the parser to check to see if
90249259Sdim  /// the specified constraint string is legal for the type.  This returns true
91249259Sdim  /// if legal, false if not.
92249259Sdim  ///
93249259Sdim  static bool Verify(FunctionType *Ty, StringRef Constraints);
94249259Sdim
95249259Sdim  // Constraint String Parsing
96249259Sdim  enum ConstraintPrefix {
97249259Sdim    isInput,            // 'x'
98249259Sdim    isOutput,           // '=x'
99249259Sdim    isClobber           // '~x'
100249259Sdim  };
101249259Sdim
102249259Sdim  typedef std::vector<std::string> ConstraintCodeVector;
103249259Sdim
104249259Sdim  struct SubConstraintInfo {
105249259Sdim    /// MatchingInput - If this is not -1, this is an output constraint where an
106249259Sdim    /// input constraint is required to match it (e.g. "0").  The value is the
107249259Sdim    /// constraint number that matches this one (for example, if this is
108249259Sdim    /// constraint #0 and constraint #4 has the value "0", this will be 4).
109249259Sdim    signed char MatchingInput;
110249259Sdim    /// Code - The constraint code, either the register name (in braces) or the
111249259Sdim    /// constraint letter/number.
112249259Sdim    ConstraintCodeVector Codes;
113249259Sdim    /// Default constructor.
114249259Sdim    SubConstraintInfo() : MatchingInput(-1) {}
115249259Sdim  };
116249259Sdim
117249259Sdim  typedef std::vector<SubConstraintInfo> SubConstraintInfoVector;
118249259Sdim  struct ConstraintInfo;
119249259Sdim  typedef std::vector<ConstraintInfo> ConstraintInfoVector;
120249259Sdim
121249259Sdim  struct ConstraintInfo {
122249259Sdim    /// Type - The basic type of the constraint: input/output/clobber
123249259Sdim    ///
124249259Sdim    ConstraintPrefix Type;
125249259Sdim
126249259Sdim    /// isEarlyClobber - "&": output operand writes result before inputs are all
127249259Sdim    /// read.  This is only ever set for an output operand.
128249259Sdim    bool isEarlyClobber;
129249259Sdim
130249259Sdim    /// MatchingInput - If this is not -1, this is an output constraint where an
131249259Sdim    /// input constraint is required to match it (e.g. "0").  The value is the
132249259Sdim    /// constraint number that matches this one (for example, if this is
133249259Sdim    /// constraint #0 and constraint #4 has the value "0", this will be 4).
134249259Sdim    signed char MatchingInput;
135249259Sdim
136249259Sdim    /// hasMatchingInput - Return true if this is an output constraint that has
137249259Sdim    /// a matching input constraint.
138249259Sdim    bool hasMatchingInput() const { return MatchingInput != -1; }
139249259Sdim
140249259Sdim    /// isCommutative - This is set to true for a constraint that is commutative
141249259Sdim    /// with the next operand.
142249259Sdim    bool isCommutative;
143249259Sdim
144249259Sdim    /// isIndirect - True if this operand is an indirect operand.  This means
145249259Sdim    /// that the address of the source or destination is present in the call
146249259Sdim    /// instruction, instead of it being returned or passed in explicitly.  This
147249259Sdim    /// is represented with a '*' in the asm string.
148249259Sdim    bool isIndirect;
149249259Sdim
150249259Sdim    /// Code - The constraint code, either the register name (in braces) or the
151249259Sdim    /// constraint letter/number.
152249259Sdim    ConstraintCodeVector Codes;
153249259Sdim
154249259Sdim    /// isMultipleAlternative - '|': has multiple-alternative constraints.
155249259Sdim    bool isMultipleAlternative;
156249259Sdim
157249259Sdim    /// multipleAlternatives - If there are multiple alternative constraints,
158249259Sdim    /// this array will contain them.  Otherwise it will be empty.
159249259Sdim    SubConstraintInfoVector multipleAlternatives;
160249259Sdim
161249259Sdim    /// The currently selected alternative constraint index.
162249259Sdim    unsigned currentAlternativeIndex;
163249259Sdim
164249259Sdim    ///Default constructor.
165249259Sdim    ConstraintInfo();
166249259Sdim
167249259Sdim    /// Copy constructor.
168249259Sdim    ConstraintInfo(const ConstraintInfo &other);
169249259Sdim
170249259Sdim    /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the
171249259Sdim    /// fields in this structure.  If the constraint string is not understood,
172249259Sdim    /// return true, otherwise return false.
173249259Sdim    bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar);
174249259Sdim
175249259Sdim    /// selectAlternative - Point this constraint to the alternative constraint
176249259Sdim    /// indicated by the index.
177249259Sdim    void selectAlternative(unsigned index);
178249259Sdim  };
179249259Sdim
180249259Sdim  /// ParseConstraints - Split up the constraint string into the specific
181249259Sdim  /// constraints and their prefixes.  If this returns an empty vector, and if
182249259Sdim  /// the constraint string itself isn't empty, there was an error parsing.
183249259Sdim  static ConstraintInfoVector ParseConstraints(StringRef ConstraintString);
184249259Sdim
185249259Sdim  /// ParseConstraints - Parse the constraints of this inlineasm object,
186249259Sdim  /// returning them the same way that ParseConstraints(str) does.
187249259Sdim  ConstraintInfoVector ParseConstraints() const {
188249259Sdim    return ParseConstraints(Constraints);
189249259Sdim  }
190249259Sdim
191249259Sdim  // Methods for support type inquiry through isa, cast, and dyn_cast:
192249259Sdim  static inline bool classof(const Value *V) {
193249259Sdim    return V->getValueID() == Value::InlineAsmVal;
194249259Sdim  }
195249259Sdim
196249259Sdim
197249259Sdim  // These are helper methods for dealing with flags in the INLINEASM SDNode
198249259Sdim  // in the backend.
199249259Sdim
200263508Sdim  enum LLVM_ENUM_INT_TYPE(uint32_t) {
201249259Sdim    // Fixed operands on an INLINEASM SDNode.
202249259Sdim    Op_InputChain = 0,
203249259Sdim    Op_AsmString = 1,
204249259Sdim    Op_MDNode = 2,
205249259Sdim    Op_ExtraInfo = 3,    // HasSideEffects, IsAlignStack, AsmDialect.
206249259Sdim    Op_FirstOperand = 4,
207249259Sdim
208249259Sdim    // Fixed operands on an INLINEASM MachineInstr.
209249259Sdim    MIOp_AsmString = 0,
210249259Sdim    MIOp_ExtraInfo = 1,    // HasSideEffects, IsAlignStack, AsmDialect.
211249259Sdim    MIOp_FirstOperand = 2,
212249259Sdim
213249259Sdim    // Interpretation of the MIOp_ExtraInfo bit field.
214249259Sdim    Extra_HasSideEffects = 1,
215249259Sdim    Extra_IsAlignStack = 2,
216249259Sdim    Extra_AsmDialect = 4,
217249259Sdim    Extra_MayLoad = 8,
218249259Sdim    Extra_MayStore = 16,
219249259Sdim
220249259Sdim    // Inline asm operands map to multiple SDNode / MachineInstr operands.
221249259Sdim    // The first operand is an immediate describing the asm operand, the low
222249259Sdim    // bits is the kind:
223249259Sdim    Kind_RegUse = 1,             // Input register, "r".
224249259Sdim    Kind_RegDef = 2,             // Output register, "=r".
225249259Sdim    Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r".
226249259Sdim    Kind_Clobber = 4,            // Clobbered register, "~r".
227249259Sdim    Kind_Imm = 5,                // Immediate.
228249259Sdim    Kind_Mem = 6,                // Memory operand, "m".
229249259Sdim
230249259Sdim    Flag_MatchingOperand = 0x80000000
231249259Sdim  };
232249259Sdim
233249259Sdim  static unsigned getFlagWord(unsigned Kind, unsigned NumOps) {
234249259Sdim    assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!");
235249259Sdim    assert(Kind >= Kind_RegUse && Kind <= Kind_Mem && "Invalid Kind");
236249259Sdim    return Kind | (NumOps << 3);
237249259Sdim  }
238249259Sdim
239249259Sdim  /// getFlagWordForMatchingOp - Augment an existing flag word returned by
240249259Sdim  /// getFlagWord with information indicating that this input operand is tied
241249259Sdim  /// to a previous output operand.
242249259Sdim  static unsigned getFlagWordForMatchingOp(unsigned InputFlag,
243249259Sdim                                           unsigned MatchedOperandNo) {
244249259Sdim    assert(MatchedOperandNo <= 0x7fff && "Too big matched operand");
245249259Sdim    assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
246249259Sdim    return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16);
247249259Sdim  }
248249259Sdim
249249259Sdim  /// getFlagWordForRegClass - Augment an existing flag word returned by
250249259Sdim  /// getFlagWord with the required register class for the following register
251249259Sdim  /// operands.
252249259Sdim  /// A tied use operand cannot have a register class, use the register class
253249259Sdim  /// from the def operand instead.
254249259Sdim  static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) {
255249259Sdim    // Store RC + 1, reserve the value 0 to mean 'no register class'.
256249259Sdim    ++RC;
257249259Sdim    assert(RC <= 0x7fff && "Too large register class ID");
258249259Sdim    assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
259249259Sdim    return InputFlag | (RC << 16);
260249259Sdim  }
261249259Sdim
262249259Sdim  static unsigned getKind(unsigned Flags) {
263249259Sdim    return Flags & 7;
264249259Sdim  }
265249259Sdim
266249259Sdim  static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;}
267249259Sdim  static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; }
268249259Sdim  static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; }
269249259Sdim  static bool isRegDefEarlyClobberKind(unsigned Flag) {
270249259Sdim    return getKind(Flag) == Kind_RegDefEarlyClobber;
271249259Sdim  }
272249259Sdim  static bool isClobberKind(unsigned Flag) {
273249259Sdim    return getKind(Flag) == Kind_Clobber;
274249259Sdim  }
275249259Sdim
276249259Sdim  /// getNumOperandRegisters - Extract the number of registers field from the
277249259Sdim  /// inline asm operand flag.
278249259Sdim  static unsigned getNumOperandRegisters(unsigned Flag) {
279249259Sdim    return (Flag & 0xffff) >> 3;
280249259Sdim  }
281249259Sdim
282249259Sdim  /// isUseOperandTiedToDef - Return true if the flag of the inline asm
283249259Sdim  /// operand indicates it is an use operand that's matched to a def operand.
284249259Sdim  static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) {
285249259Sdim    if ((Flag & Flag_MatchingOperand) == 0)
286249259Sdim      return false;
287249259Sdim    Idx = (Flag & ~Flag_MatchingOperand) >> 16;
288249259Sdim    return true;
289249259Sdim  }
290249259Sdim
291249259Sdim  /// hasRegClassConstraint - Returns true if the flag contains a register
292249259Sdim  /// class constraint.  Sets RC to the register class ID.
293249259Sdim  static bool hasRegClassConstraint(unsigned Flag, unsigned &RC) {
294249259Sdim    if (Flag & Flag_MatchingOperand)
295249259Sdim      return false;
296249259Sdim    unsigned High = Flag >> 16;
297249259Sdim    // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise
298249259Sdim    // stores RC + 1.
299249259Sdim    if (!High)
300249259Sdim      return false;
301249259Sdim    RC = High - 1;
302249259Sdim    return true;
303249259Sdim  }
304249259Sdim
305249259Sdim};
306249259Sdim
307249259Sdim} // End llvm namespace
308249259Sdim
309249259Sdim#endif
310