LLVM  8.0.1
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  StructType *ST = cast<StructType>(T);
79  if (ST->getNumElements() != 2)
80  break;
81  if ((ST->getElementType(0)->isFloatTy()) &&
82  (ST->getElementType(1)->isFloatTy()))
83  return CFRet;
84  if ((ST->getElementType(0)->isDoubleTy()) &&
85  (ST->getElementType(1)->isDoubleTy()))
86  return CDRet;
87  break;
88  }
89  default:
90  break;
91  }
92  return NoFPRet;
93 }
94 
95 // Parameter type that matter are float, (float, float), (float, double),
96 // double, (double, double), (double, float)
100 };
101 
102 // which floating point parameter signature variant we are dealing with
106 
108  switch (F.arg_size()) {
109  case 0:
110  return NoSig;
111  case 1:{
112  TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID();
113  switch (ArgTypeID) {
114  case FloatTyID:
115  return FSig;
116  case DoubleTyID:
117  return DSig;
118  default:
119  return NoSig;
120  }
121  }
122  default: {
123  TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID();
124  TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID();
125  switch(ArgTypeID0) {
126  case FloatTyID: {
127  switch (ArgTypeID1) {
128  case FloatTyID:
129  return FFSig;
130  case DoubleTyID:
131  return FDSig;
132  default:
133  return FSig;
134  }
135  }
136  case DoubleTyID: {
137  switch (ArgTypeID1) {
138  case FloatTyID:
139  return DFSig;
140  case DoubleTyID:
141  return DDSig;
142  default:
143  return DSig;
144  }
145  }
146  default:
147  return NoSig;
148  }
149  }
150  }
151  llvm_unreachable("can't get here");
152 }
153 
154 // Figure out if we need float point based on the function parameters.
155 // We need to move variables in and/or out of floating point
156 // registers because of the ABI
158  if (F.arg_size() >=1) {
159  Type *ArgType = F.getFunctionType()->getParamType(0);
160  switch (ArgType->getTypeID()) {
161  case Type::FloatTyID:
162  case Type::DoubleTyID:
163  return true;
164  default:
165  break;
166  }
167  }
168  return false;
169 }
170 
172  Type* RetType = F.getReturnType();
173  return whichFPReturnVariant(RetType) != NoFPRet;
174 }
175 
177  Type* RetType = FT.getReturnType();
178  return whichFPReturnVariant(RetType) != NoFPRet;
179 }
180 
183 }
184 
185 // We swap between FP and Integer registers to allow Mips16 and Mips32 to
186 // interoperate
187 static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE,
188  bool ToFP) {
189  std::string MI = ToFP ? "mtc1 ": "mfc1 ";
190  std::string AsmText;
191 
192  switch (PV) {
193  case FSig:
194  AsmText += MI + "$$4, $$f12\n";
195  break;
196 
197  case FFSig:
198  AsmText += MI + "$$4, $$f12\n";
199  AsmText += MI + "$$5, $$f14\n";
200  break;
201 
202  case FDSig:
203  AsmText += MI + "$$4, $$f12\n";
204  if (LE) {
205  AsmText += MI + "$$6, $$f14\n";
206  AsmText += MI + "$$7, $$f15\n";
207  } else {
208  AsmText += MI + "$$7, $$f14\n";
209  AsmText += MI + "$$6, $$f15\n";
210  }
211  break;
212 
213  case DSig:
214  if (LE) {
215  AsmText += MI + "$$4, $$f12\n";
216  AsmText += MI + "$$5, $$f13\n";
217  } else {
218  AsmText += MI + "$$5, $$f12\n";
219  AsmText += MI + "$$4, $$f13\n";
220  }
221  break;
222 
223  case DDSig:
224  if (LE) {
225  AsmText += MI + "$$4, $$f12\n";
226  AsmText += MI + "$$5, $$f13\n";
227  AsmText += MI + "$$6, $$f14\n";
228  AsmText += MI + "$$7, $$f15\n";
229  } else {
230  AsmText += MI + "$$5, $$f12\n";
231  AsmText += MI + "$$4, $$f13\n";
232  AsmText += MI + "$$7, $$f14\n";
233  AsmText += MI + "$$6, $$f15\n";
234  }
235  break;
236 
237  case DFSig:
238  if (LE) {
239  AsmText += MI + "$$4, $$f12\n";
240  AsmText += MI + "$$5, $$f13\n";
241  } else {
242  AsmText += MI + "$$5, $$f12\n";
243  AsmText += MI + "$$4, $$f13\n";
244  }
245  AsmText += MI + "$$6, $$f14\n";
246  break;
247 
248  case NoSig:
249  break;
250  }
251 
252  return AsmText;
253 }
254 
255 // Make sure that we know we already need a stub for this function.
256 // Having called needsFPHelperFromSig
258  const MipsTargetMachine &TM) {
259  // for now we only need them for static relocation
260  if (TM.isPositionIndependent())
261  return;
263  bool LE = TM.isLittleEndian();
264  std::string Name = F.getName();
265  std::string SectionName = ".mips16.call.fp." + Name;
266  std::string StubName = "__call_stub_fp_" + Name;
267  //
268  // see if we already have the stub
269  //
270  Function *FStub = M->getFunction(StubName);
271  if (FStub && !FStub->isDeclaration()) return;
272  FStub = Function::Create(F.getFunctionType(),
273  Function::InternalLinkage, StubName, M);
274  FStub->addFnAttr("mips16_fp_stub");
275  FStub->addFnAttr(Attribute::Naked);
278  FStub->addFnAttr("nomips16");
279  FStub->setSection(SectionName);
280  BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
283 
284  std::string AsmText;
285  AsmText += ".set reorder\n";
286  AsmText += swapFPIntParams(PV, M, LE, true);
287  if (RV != NoFPRet) {
288  AsmText += "move $$18, $$31\n";
289  AsmText += "jal " + Name + "\n";
290  } else {
291  AsmText += "lui $$25, %hi(" + Name + ")\n";
292  AsmText += "addiu $$25, $$25, %lo(" + Name + ")\n";
293  }
294 
295  switch (RV) {
296  case FRet:
297  AsmText += "mfc1 $$2, $$f0\n";
298  break;
299 
300  case DRet:
301  if (LE) {
302  AsmText += "mfc1 $$2, $$f0\n";
303  AsmText += "mfc1 $$3, $$f1\n";
304  } else {
305  AsmText += "mfc1 $$3, $$f0\n";
306  AsmText += "mfc1 $$2, $$f1\n";
307  }
308  break;
309 
310  case CFRet:
311  if (LE) {
312  AsmText += "mfc1 $$2, $$f0\n";
313  AsmText += "mfc1 $$3, $$f2\n";
314  } else {
315  AsmText += "mfc1 $$3, $$f0\n";
316  AsmText += "mfc1 $$3, $$f2\n";
317  }
318  break;
319 
320  case CDRet:
321  if (LE) {
322  AsmText += "mfc1 $$4, $$f2\n";
323  AsmText += "mfc1 $$5, $$f3\n";
324  AsmText += "mfc1 $$2, $$f0\n";
325  AsmText += "mfc1 $$3, $$f1\n";
326 
327  } else {
328  AsmText += "mfc1 $$5, $$f2\n";
329  AsmText += "mfc1 $$4, $$f3\n";
330  AsmText += "mfc1 $$3, $$f0\n";
331  AsmText += "mfc1 $$2, $$f1\n";
332  }
333  break;
334 
335  case NoFPRet:
336  break;
337  }
338 
339  if (RV != NoFPRet)
340  AsmText += "jr $$18\n";
341  else
342  AsmText += "jr $$25\n";
343  EmitInlineAsm(Context, BB, AsmText);
344 
345  new UnreachableInst(Context, BB);
346 }
347 
348 // Functions that are llvm intrinsics and don't need helpers.
349 static const char *const IntrinsicInline[] = {
350  "fabs", "fabsf",
351  "llvm.ceil.f32", "llvm.ceil.f64",
352  "llvm.copysign.f32", "llvm.copysign.f64",
353  "llvm.cos.f32", "llvm.cos.f64",
354  "llvm.exp.f32", "llvm.exp.f64",
355  "llvm.exp2.f32", "llvm.exp2.f64",
356  "llvm.fabs.f32", "llvm.fabs.f64",
357  "llvm.floor.f32", "llvm.floor.f64",
358  "llvm.fma.f32", "llvm.fma.f64",
359  "llvm.log.f32", "llvm.log.f64",
360  "llvm.log10.f32", "llvm.log10.f64",
361  "llvm.nearbyint.f32", "llvm.nearbyint.f64",
362  "llvm.pow.f32", "llvm.pow.f64",
363  "llvm.powi.f32", "llvm.powi.f64",
364  "llvm.rint.f32", "llvm.rint.f64",
365  "llvm.round.f32", "llvm.round.f64",
366  "llvm.sin.f32", "llvm.sin.f64",
367  "llvm.sqrt.f32", "llvm.sqrt.f64",
368  "llvm.trunc.f32", "llvm.trunc.f64",
369 };
370 
371 static bool isIntrinsicInline(Function *F) {
372  return std::binary_search(std::begin(IntrinsicInline),
373  std::end(IntrinsicInline), F->getName());
374 }
375 
376 // Returns of float, double and complex need to be handled with a helper
377 // function.
379  const MipsTargetMachine &TM) {
380  bool Modified = false;
381  LLVMContext &C = M->getContext();
382  Type *MyVoid = Type::getVoidTy(C);
383  for (auto &BB: F)
384  for (auto &I: BB) {
385  if (const ReturnInst *RI = dyn_cast<ReturnInst>(&I)) {
386  Value *RVal = RI->getReturnValue();
387  if (!RVal) continue;
388  //
389  // If there is a return value and it needs a helper function,
390  // figure out which one and add a call before the actual
391  // return to this helper. The purpose of the helper is to move
392  // floating point values from their soft float return mapping to
393  // where they would have been mapped to in floating point registers.
394  //
395  Type *T = RVal->getType();
397  if (RV == NoFPRet) continue;
398  static const char *const Helper[NoFPRet] = {
399  "__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",
400  "__mips16_ret_dc"
401  };
402  const char *Name = Helper[RV];
403  AttributeList A;
404  Value *Params[] = {RVal};
405  Modified = true;
406  //
407  // These helper functions have a different calling ABI so
408  // this __Mips16RetHelper indicates that so that later
409  // during call setup, the proper call lowering to the helper
410  // functions will take place.
411  //
413  "__Mips16RetHelper");
418  Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T));
419  CallInst::Create(F, Params, "", &I);
420  } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
421  FunctionType *FT = CI->getFunctionType();
422  Function *F_ = CI->getCalledFunction();
423  if (needsFPReturnHelper(*FT) &&
424  !(F_ && isIntrinsicInline(F_))) {
425  Modified=true;
426  F.addFnAttr("saveS2");
427  }
428  if (F_ && !isIntrinsicInline(F_)) {
429  // pic mode calls are handled by already defined
430  // helper functions
431  if (needsFPReturnHelper(*F_)) {
432  Modified=true;
433  F.addFnAttr("saveS2");
434  }
435  if (!TM.isPositionIndependent()) {
436  if (needsFPHelperFromSig(*F_)) {
437  assureFPCallStub(*F_, M, TM);
438  Modified=true;
439  }
440  }
441  }
442  }
443  }
444  return Modified;
445 }
446 
448  const MipsTargetMachine &TM) {
449  bool PicMode = TM.isPositionIndependent();
450  bool LE = TM.isLittleEndian();
452  std::string Name = F->getName();
453  std::string SectionName = ".mips16.fn." + Name;
454  std::string StubName = "__fn_stub_" + Name;
455  std::string LocalName = "$$__fn_local_" + Name;
456  Function *FStub = Function::Create
457  (F->getFunctionType(),
458  Function::InternalLinkage, StubName, M);
459  FStub->addFnAttr("mips16_fp_stub");
460  FStub->addFnAttr(Attribute::Naked);
463  FStub->addFnAttr("nomips16");
464  FStub->setSection(SectionName);
465  BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
466 
467  std::string AsmText;
468  if (PicMode) {
469  AsmText += ".set noreorder\n";
470  AsmText += ".cpload $$25\n";
471  AsmText += ".set reorder\n";
472  AsmText += ".reloc 0, R_MIPS_NONE, " + Name + "\n";
473  AsmText += "la $$25, " + LocalName + "\n";
474  } else
475  AsmText += "la $$25, " + Name + "\n";
476  AsmText += swapFPIntParams(PV, M, LE, false);
477  AsmText += "jr $$25\n";
478  AsmText += LocalName + " = " + Name + "\n";
479  EmitInlineAsm(Context, BB, AsmText);
480 
481  new UnreachableInst(FStub->getContext(), BB);
482 }
483 
484 // remove the use-soft-float attribute
486  AttrBuilder B;
487  LLVM_DEBUG(errs() << "removing -use-soft-float\n");
488  B.addAttribute("use-soft-float", "false");
490  if (F.hasFnAttribute("use-soft-float")) {
491  LLVM_DEBUG(errs() << "still has -use-soft-float\n");
492  }
494 }
495 
496 // This pass only makes sense when the underlying chip has floating point but
497 // we are compiling as mips16.
498 // For all mips16 functions (that are not stubs we have already generated), or
499 // declared via attributes as nomips16, we must:
500 // 1) fixup all returns of float, double, single and double complex
501 // by calling a helper function before the actual return.
502 // 2) generate helper functions (stubs) that can be called by mips32
503 // functions that will move parameters passed normally passed in
504 // floating point
505 // registers the soft float equivalents.
506 // 3) in the case of static relocation, generate helper functions so that
507 // mips16 functions can call extern functions of unknown type (mips16 or
508 // mips32).
509 // 4) TBD. For pic, calls to extern functions of unknown type are handled by
510 // predefined helper functions in libc but this work is currently done
511 // during call lowering but it should be moved here in the future.
512 bool Mips16HardFloat::runOnModule(Module &M) {
513  auto &TM = static_cast<const MipsTargetMachine &>(
514  getAnalysis<TargetPassConfig>().getTM<TargetMachine>());
515  LLVM_DEBUG(errs() << "Run on Module Mips16HardFloat\n");
516  bool Modified = false;
517  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
518  if (F->hasFnAttribute("nomips16") &&
519  F->hasFnAttribute("use-soft-float")) {
521  continue;
522  }
523  if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") ||
524  F->hasFnAttribute("nomips16")) continue;
525  Modified |= fixupFPReturnAndCall(*F, &M, TM);
527  if (V != NoSig) {
528  Modified = true;
529  createFPFnStub(&*F, &M, V, TM);
530  }
531  }
532  return Modified;
533 }
534 
536  return new Mips16HardFloat();
537 }
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:259
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:250
This class represents lattice values for constants.
Definition: AllocatorList.h:24
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:135
Type * getElementType(unsigned N) const
Definition: DerivedTypes.h:314
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:144
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
2: 32-bit floating point type
Definition: Type.h:59
static void removeUseSoftFloat(Function &F)
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
unsigned getNumElements() const
Random access to the elements.
Definition: DerivedTypes.h:313
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:321
13: Structures
Definition: Type.h:73
F(f)
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
AnalysisUsage & addRequired()
amdgpu Simplify well known AMD library false Value Value const Twine & Name
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:138
Class to represent struct types.
Definition: DerivedTypes.h:201
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:244
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:92
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
#define T
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:169
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:136
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
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:698
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:100
ModulePass * createMips16HardFloatPass()
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:193
#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:176
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:164
void removeAttributes(unsigned i, const AttrBuilder &Attrs)
removes the attributes from the list of attributes.
Definition: Function.cpp:416
LLVM_NODISCARD 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:597
static const char *const IntrinsicInline[]
bool isPositionIndependent() const
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
#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:595
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:206
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:380
const Type::TypeID DoubleTyID
LLVM Value Representation.
Definition: Value.h:73
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition: Function.h:230
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
#define LLVM_DEBUG(X)
Definition: Debug.h:123
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:189
static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE, bool ToFP)