LLVM  6.0.0svn
Mips16HardFloat.cpp
Go to the documentation of this file.
1 //===- Mips16HardFloat.cpp for Mips16 Hard Float --------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a pass needed for Mips16 Hard Float
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MipsTargetMachine.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/Value.h"
18 #include "llvm/Support/Debug.h"
20 #include <algorithm>
21 #include <string>
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "mips16-hard-float"
26 
27 namespace {
28 
29  class Mips16HardFloat : public ModulePass {
30  public:
31  static char ID;
32 
33  Mips16HardFloat() : ModulePass(ID) {}
34 
35  StringRef getPassName() const override { return "MIPS16 Hard Float Pass"; }
36 
37  void getAnalysisUsage(AnalysisUsage &AU) const override {
40  }
41 
42  bool runOnModule(Module &M) override;
43  };
44 
45 } // end anonymous namespace
46 
47 static void EmitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText) {
48  std::vector<Type *> AsmArgTypes;
49  std::vector<Value *> AsmArgs;
50 
51  FunctionType *AsmFTy =
52  FunctionType::get(Type::getVoidTy(C), AsmArgTypes, false);
53  InlineAsm *IA = InlineAsm::get(AsmFTy, AsmText, "", true,
54  /* IsAlignStack */ false, InlineAsm::AD_ATT);
55  CallInst::Create(IA, AsmArgs, "", BB);
56 }
57 
58 char Mips16HardFloat::ID = 0;
59 
60 //
61 // Return types that matter for hard float are:
62 // float, double, complex float, and complex double
63 //
66 };
67 
68 //
69 // Determine which FP return type this function has
70 //
72  switch (T->getTypeID()) {
73  case Type::FloatTyID:
74  return FRet;
75  case Type::DoubleTyID:
76  return DRet;
77  case Type::StructTyID:
78  if (T->getStructNumElements() != 2)
79  break;
80  if ((T->getContainedType(0)->isFloatTy()) &&
81  (T->getContainedType(1)->isFloatTy()))
82  return CFRet;
83  if ((T->getContainedType(0)->isDoubleTy()) &&
84  (T->getContainedType(1)->isDoubleTy()))
85  return CDRet;
86  break;
87  default:
88  break;
89  }
90  return NoFPRet;
91 }
92 
93 // Parameter type that matter are float, (float, float), (float, double),
94 // double, (double, double), (double, float)
98 };
99 
100 // which floating point parameter signature variant we are dealing with
104 
106  switch (F.arg_size()) {
107  case 0:
108  return NoSig;
109  case 1:{
110  TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID();
111  switch (ArgTypeID) {
112  case FloatTyID:
113  return FSig;
114  case DoubleTyID:
115  return DSig;
116  default:
117  return NoSig;
118  }
119  }
120  default: {
121  TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID();
122  TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID();
123  switch(ArgTypeID0) {
124  case FloatTyID: {
125  switch (ArgTypeID1) {
126  case FloatTyID:
127  return FFSig;
128  case DoubleTyID:
129  return FDSig;
130  default:
131  return FSig;
132  }
133  }
134  case DoubleTyID: {
135  switch (ArgTypeID1) {
136  case FloatTyID:
137  return DFSig;
138  case DoubleTyID:
139  return DDSig;
140  default:
141  return DSig;
142  }
143  }
144  default:
145  return NoSig;
146  }
147  }
148  }
149  llvm_unreachable("can't get here");
150 }
151 
152 // Figure out if we need float point based on the function parameters.
153 // We need to move variables in and/or out of floating point
154 // registers because of the ABI
156  if (F.arg_size() >=1) {
157  Type *ArgType = F.getFunctionType()->getParamType(0);
158  switch (ArgType->getTypeID()) {
159  case Type::FloatTyID:
160  case Type::DoubleTyID:
161  return true;
162  default:
163  break;
164  }
165  }
166  return false;
167 }
168 
170  Type* RetType = F.getReturnType();
171  return whichFPReturnVariant(RetType) != NoFPRet;
172 }
173 
175  Type* RetType = FT.getReturnType();
176  return whichFPReturnVariant(RetType) != NoFPRet;
177 }
178 
181 }
182 
183 // We swap between FP and Integer registers to allow Mips16 and Mips32 to
184 // interoperate
185 static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE,
186  bool ToFP) {
187  std::string MI = ToFP ? "mtc1 ": "mfc1 ";
188  std::string AsmText;
189 
190  switch (PV) {
191  case FSig:
192  AsmText += MI + "$$4, $$f12\n";
193  break;
194 
195  case FFSig:
196  AsmText += MI + "$$4, $$f12\n";
197  AsmText += MI + "$$5, $$f14\n";
198  break;
199 
200  case FDSig:
201  AsmText += MI + "$$4, $$f12\n";
202  if (LE) {
203  AsmText += MI + "$$6, $$f14\n";
204  AsmText += MI + "$$7, $$f15\n";
205  } else {
206  AsmText += MI + "$$7, $$f14\n";
207  AsmText += MI + "$$6, $$f15\n";
208  }
209  break;
210 
211  case DSig:
212  if (LE) {
213  AsmText += MI + "$$4, $$f12\n";
214  AsmText += MI + "$$5, $$f13\n";
215  } else {
216  AsmText += MI + "$$5, $$f12\n";
217  AsmText += MI + "$$4, $$f13\n";
218  }
219  break;
220 
221  case DDSig:
222  if (LE) {
223  AsmText += MI + "$$4, $$f12\n";
224  AsmText += MI + "$$5, $$f13\n";
225  AsmText += MI + "$$6, $$f14\n";
226  AsmText += MI + "$$7, $$f15\n";
227  } else {
228  AsmText += MI + "$$5, $$f12\n";
229  AsmText += MI + "$$4, $$f13\n";
230  AsmText += MI + "$$7, $$f14\n";
231  AsmText += MI + "$$6, $$f15\n";
232  }
233  break;
234 
235  case DFSig:
236  if (LE) {
237  AsmText += MI + "$$4, $$f12\n";
238  AsmText += MI + "$$5, $$f13\n";
239  } else {
240  AsmText += MI + "$$5, $$f12\n";
241  AsmText += MI + "$$4, $$f13\n";
242  }
243  AsmText += MI + "$$6, $$f14\n";
244  break;
245 
246  case NoSig:
247  break;
248  }
249 
250  return AsmText;
251 }
252 
253 // Make sure that we know we already need a stub for this function.
254 // Having called needsFPHelperFromSig
256  const MipsTargetMachine &TM) {
257  // for now we only need them for static relocation
258  if (TM.isPositionIndependent())
259  return;
261  bool LE = TM.isLittleEndian();
262  std::string Name = F.getName();
263  std::string SectionName = ".mips16.call.fp." + Name;
264  std::string StubName = "__call_stub_fp_" + Name;
265  //
266  // see if we already have the stub
267  //
268  Function *FStub = M->getFunction(StubName);
269  if (FStub && !FStub->isDeclaration()) return;
270  FStub = Function::Create(F.getFunctionType(),
271  Function::InternalLinkage, StubName, M);
272  FStub->addFnAttr("mips16_fp_stub");
273  FStub->addFnAttr(Attribute::Naked);
274  FStub->addFnAttr(Attribute::NoInline);
275  FStub->addFnAttr(Attribute::NoUnwind);
276  FStub->addFnAttr("nomips16");
277  FStub->setSection(SectionName);
278  BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
281 
282  std::string AsmText;
283  AsmText += ".set reorder\n";
284  AsmText += swapFPIntParams(PV, M, LE, true);
285  if (RV != NoFPRet) {
286  AsmText += "move $$18, $$31\n";
287  AsmText += "jal " + Name + "\n";
288  } else {
289  AsmText += "lui $$25, %hi(" + Name + ")\n";
290  AsmText += "addiu $$25, $$25, %lo(" + Name + ")\n";
291  }
292 
293  switch (RV) {
294  case FRet:
295  AsmText += "mfc1 $$2, $$f0\n";
296  break;
297 
298  case DRet:
299  if (LE) {
300  AsmText += "mfc1 $$2, $$f0\n";
301  AsmText += "mfc1 $$3, $$f1\n";
302  } else {
303  AsmText += "mfc1 $$3, $$f0\n";
304  AsmText += "mfc1 $$2, $$f1\n";
305  }
306  break;
307 
308  case CFRet:
309  if (LE) {
310  AsmText += "mfc1 $$2, $$f0\n";
311  AsmText += "mfc1 $$3, $$f2\n";
312  } else {
313  AsmText += "mfc1 $$3, $$f0\n";
314  AsmText += "mfc1 $$3, $$f2\n";
315  }
316  break;
317 
318  case CDRet:
319  if (LE) {
320  AsmText += "mfc1 $$4, $$f2\n";
321  AsmText += "mfc1 $$5, $$f3\n";
322  AsmText += "mfc1 $$2, $$f0\n";
323  AsmText += "mfc1 $$3, $$f1\n";
324 
325  } else {
326  AsmText += "mfc1 $$5, $$f2\n";
327  AsmText += "mfc1 $$4, $$f3\n";
328  AsmText += "mfc1 $$3, $$f0\n";
329  AsmText += "mfc1 $$2, $$f1\n";
330  }
331  break;
332 
333  case NoFPRet:
334  break;
335  }
336 
337  if (RV != NoFPRet)
338  AsmText += "jr $$18\n";
339  else
340  AsmText += "jr $$25\n";
341  EmitInlineAsm(Context, BB, AsmText);
342 
343  new UnreachableInst(Context, BB);
344 }
345 
346 // Functions that are llvm intrinsics and don't need helpers.
347 static const char *const IntrinsicInline[] = {
348  "fabs", "fabsf",
349  "llvm.ceil.f32", "llvm.ceil.f64",
350  "llvm.copysign.f32", "llvm.copysign.f64",
351  "llvm.cos.f32", "llvm.cos.f64",
352  "llvm.exp.f32", "llvm.exp.f64",
353  "llvm.exp2.f32", "llvm.exp2.f64",
354  "llvm.fabs.f32", "llvm.fabs.f64",
355  "llvm.floor.f32", "llvm.floor.f64",
356  "llvm.fma.f32", "llvm.fma.f64",
357  "llvm.log.f32", "llvm.log.f64",
358  "llvm.log10.f32", "llvm.log10.f64",
359  "llvm.nearbyint.f32", "llvm.nearbyint.f64",
360  "llvm.pow.f32", "llvm.pow.f64",
361  "llvm.powi.f32", "llvm.powi.f64",
362  "llvm.rint.f32", "llvm.rint.f64",
363  "llvm.round.f32", "llvm.round.f64",
364  "llvm.sin.f32", "llvm.sin.f64",
365  "llvm.sqrt.f32", "llvm.sqrt.f64",
366  "llvm.trunc.f32", "llvm.trunc.f64",
367 };
368 
369 static bool isIntrinsicInline(Function *F) {
370  return std::binary_search(std::begin(IntrinsicInline),
371  std::end(IntrinsicInline), F->getName());
372 }
373 
374 // Returns of float, double and complex need to be handled with a helper
375 // function.
377  const MipsTargetMachine &TM) {
378  bool Modified = false;
379  LLVMContext &C = M->getContext();
380  Type *MyVoid = Type::getVoidTy(C);
381  for (auto &BB: F)
382  for (auto &I: BB) {
383  if (const ReturnInst *RI = dyn_cast<ReturnInst>(&I)) {
384  Value *RVal = RI->getReturnValue();
385  if (!RVal) continue;
386  //
387  // If there is a return value and it needs a helper function,
388  // figure out which one and add a call before the actual
389  // return to this helper. The purpose of the helper is to move
390  // floating point values from their soft float return mapping to
391  // where they would have been mapped to in floating point registers.
392  //
393  Type *T = RVal->getType();
395  if (RV == NoFPRet) continue;
396  static const char *const Helper[NoFPRet] = {
397  "__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",
398  "__mips16_ret_dc"
399  };
400  const char *Name = Helper[RV];
401  AttributeList A;
402  Value *Params[] = {RVal};
403  Modified = true;
404  //
405  // These helper functions have a different calling ABI so
406  // this __Mips16RetHelper indicates that so that later
407  // during call setup, the proper call lowering to the helper
408  // functions will take place.
409  //
411  "__Mips16RetHelper");
413  Attribute::ReadNone);
415  Attribute::NoInline);
416  Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T));
417  CallInst::Create(F, Params, "", &I);
418  } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
419  FunctionType *FT = CI->getFunctionType();
420  Function *F_ = CI->getCalledFunction();
421  if (needsFPReturnHelper(*FT) &&
422  !(F_ && isIntrinsicInline(F_))) {
423  Modified=true;
424  F.addFnAttr("saveS2");
425  }
426  if (F_ && !isIntrinsicInline(F_)) {
427  // pic mode calls are handled by already defined
428  // helper functions
429  if (needsFPReturnHelper(*F_)) {
430  Modified=true;
431  F.addFnAttr("saveS2");
432  }
433  if (!TM.isPositionIndependent()) {
434  if (needsFPHelperFromSig(*F_)) {
435  assureFPCallStub(*F_, M, TM);
436  Modified=true;
437  }
438  }
439  }
440  }
441  }
442  return Modified;
443 }
444 
446  const MipsTargetMachine &TM) {
447  bool PicMode = TM.isPositionIndependent();
448  bool LE = TM.isLittleEndian();
450  std::string Name = F->getName();
451  std::string SectionName = ".mips16.fn." + Name;
452  std::string StubName = "__fn_stub_" + Name;
453  std::string LocalName = "$$__fn_local_" + Name;
454  Function *FStub = Function::Create
455  (F->getFunctionType(),
456  Function::InternalLinkage, StubName, M);
457  FStub->addFnAttr("mips16_fp_stub");
458  FStub->addFnAttr(Attribute::Naked);
459  FStub->addFnAttr(Attribute::NoUnwind);
460  FStub->addFnAttr(Attribute::NoInline);
461  FStub->addFnAttr("nomips16");
462  FStub->setSection(SectionName);
463  BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
464 
465  std::string AsmText;
466  if (PicMode) {
467  AsmText += ".set noreorder\n";
468  AsmText += ".cpload $$25\n";
469  AsmText += ".set reorder\n";
470  AsmText += ".reloc 0, R_MIPS_NONE, " + Name + "\n";
471  AsmText += "la $$25, " + LocalName + "\n";
472  } else
473  AsmText += "la $$25, " + Name + "\n";
474  AsmText += swapFPIntParams(PV, M, LE, false);
475  AsmText += "jr $$25\n";
476  AsmText += LocalName + " = " + Name + "\n";
477  EmitInlineAsm(Context, BB, AsmText);
478 
479  new UnreachableInst(FStub->getContext(), BB);
480 }
481 
482 // remove the use-soft-float attribute
484  AttrBuilder B;
485  DEBUG(errs() << "removing -use-soft-float\n");
486  B.addAttribute("use-soft-float", "false");
488  if (F.hasFnAttribute("use-soft-float")) {
489  DEBUG(errs() << "still has -use-soft-float\n");
490  }
492 }
493 
494 // This pass only makes sense when the underlying chip has floating point but
495 // we are compiling as mips16.
496 // For all mips16 functions (that are not stubs we have already generated), or
497 // declared via attributes as nomips16, we must:
498 // 1) fixup all returns of float, double, single and double complex
499 // by calling a helper function before the actual return.
500 // 2) generate helper functions (stubs) that can be called by mips32
501 // functions that will move parameters passed normally passed in
502 // floating point
503 // registers the soft float equivalents.
504 // 3) in the case of static relocation, generate helper functions so that
505 // mips16 functions can call extern functions of unknown type (mips16 or
506 // mips32).
507 // 4) TBD. For pic, calls to extern functions of unknown type are handled by
508 // predefined helper functions in libc but this work is currently done
509 // during call lowering but it should be moved here in the future.
510 bool Mips16HardFloat::runOnModule(Module &M) {
511  auto &TM = static_cast<const MipsTargetMachine &>(
512  getAnalysis<TargetPassConfig>().getTM<TargetMachine>());
513  DEBUG(errs() << "Run on Module Mips16HardFloat\n");
514  bool Modified = false;
515  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
516  if (F->hasFnAttribute("nomips16") &&
517  F->hasFnAttribute("use-soft-float")) {
519  continue;
520  }
521  if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") ||
522  F->hasFnAttribute("nomips16")) continue;
523  Modified |= fixupFPReturnAndCall(*F, &M, TM);
525  if (V != NoSig) {
526  Modified = true;
527  createFPFnStub(&*F, &M, V, TM);
528  }
529  }
530  return Modified;
531 }
532 
534  return new Mips16HardFloat();
535 }
uint64_t CallInst * C
Return a value (possibly void), from a function.
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:244
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVMContext & Context
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:235
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:135
static bool needsFPReturnHelper(Function &F)
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
Definition: Module.cpp:142
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:63
2: 32-bit floating point type
Definition: Type.h:59
static void removeUseSoftFloat(Function &F)
FPParamVariant
This class represents a function call, abstracting a target machine&#39;s calling convention.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.h:262
13: Structures
Definition: Type.h:73
F(f)
static CallInst * Create(Value *Func, ArrayRef< Value *> Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
AnalysisUsage & addRequired()
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:138
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:237
static bool needsFPHelperFromSig(Function &F)
TypeID
Definitions of all of the base types for the Type system.
Definition: Type.h:55
Target-Independent Code Generator Pass Configuration Options.
static bool needsFPStubFromParams(Function &F)
static FPReturnVariant whichFPReturnVariant(Type *T)
Class to represent function types.
Definition: DerivedTypes.h:103
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:91
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
const Type::TypeID FloatTyID
FPReturnVariant
static bool isIntrinsicInline(Function *F)
static void assureFPCallStub(Function &F, Module *M, const MipsTargetMachine &TM)
bool isFloatTy() const
Return true if this is &#39;float&#39;, a 32-bit IEEE fp type.
Definition: Type.h:147
Type * getReturnType() const
Returns the type of the ret val.
Definition: Function.h:150
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
LLVM Basic Block Representation.
Definition: BasicBlock.h:59
static bool fixupFPReturnAndCall(Function &F, Module *M, const MipsTargetMachine &TM)
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:69
This function has undefined behavior.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM)
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:161
static void EmitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText)
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:297
size_t arg_size() const
Definition: Function.h:630
unsigned getStructNumElements() const
Definition: DerivedTypes.h:329
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:101
ModulePass * createMips16HardFloatPass()
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:194
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
Module.h This file contains the declarations for the Module class.
Type * getReturnType() const
Definition: DerivedTypes.h:124
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
Definition: Module.cpp:172
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:145
void removeAttributes(unsigned i, const AttrBuilder &Attrs)
removes the attributes from the list of attributes.
Definition: Function.cpp:395
AttributeList addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Add an attribute to the attribute set at the given index.
static FPParamVariant whichFPParamVariantNeeded(Function &F)
iterator end()
Definition: Module.h:574
static const char *const IntrinsicInline[]
bool isPositionIndependent() const
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:220
#define I(x, y, z)
Definition: MD5.cpp:58
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:225
iterator begin()
Definition: Module.h:572
Rename collisions when linking (static functions).
Definition: GlobalValue.h:56
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
InlineAsm::get - Return the specified uniqued inline asm string.
Definition: InlineAsm.cpp:43
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:201
3: 64-bit floating point type
Definition: Type.h:60
void addAttributes(unsigned i, const AttrBuilder &Attrs)
adds the attributes to the list of attributes.
Definition: Function.cpp:359
const Type::TypeID DoubleTyID
LLVM Value Representation.
Definition: Value.h:73
#define DEBUG(X)
Definition: Debug.h:118
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition: Function.h:211
static cl::opt< bool > Mips16HardFloat("mips16-hard-float", cl::NotHidden, cl::desc("Enable mips16 hard float."), cl::init(false))
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
Definition: Function.h:136
bool isDoubleTy() const
Return true if this is &#39;double&#39;, a 64-bit IEEE fp type.
Definition: Type.h:150
void setSection(StringRef S)
Change the section for this global.
Definition: Globals.cpp:184
static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE, bool ToFP)
Type * getContainedType(unsigned i) const
This method is used to implement the type iterator (defined at the end of the file).
Definition: Type.h:330