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