LLVM  3.7.0
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"
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  class Mips16HardFloat : public ModulePass {
28  public:
29  static char ID;
30 
32 
33  const char *getPassName() const override {
34  return "MIPS16 Hard Float Pass";
35  }
36 
37  bool runOnModule(Module &M) override;
38 
39  protected:
40  const MipsTargetMachine &TM;
41  };
42 
43  class InlineAsmHelper {
44  LLVMContext &C;
45  BasicBlock *BB;
46  public:
47  InlineAsmHelper(LLVMContext &C_, BasicBlock *BB_) :
48  C(C_), BB(BB_) {
49  }
50 
51  void Out(StringRef AsmString) {
52  std::vector<llvm::Type *> AsmArgTypes;
53  std::vector<llvm::Value*> AsmArgs;
54 
56  AsmArgTypes, false);
57  llvm::InlineAsm *IA = llvm::InlineAsm::get(AsmFTy, AsmString, "", true,
58  /* IsAlignStack */ false,
60  CallInst::Create(IA, AsmArgs, "", BB);
61  }
62  };
63 
64  char Mips16HardFloat::ID = 0;
65 }
66 
67 //
68 // Return types that matter for hard float are:
69 // float, double, complex float, and complex double
70 //
73 };
74 
75 //
76 // Determine which FP return type this function has
77 //
79  switch (T->getTypeID()) {
80  case Type::FloatTyID:
81  return FRet;
82  case Type::DoubleTyID:
83  return DRet;
84  case Type::StructTyID:
85  if (T->getStructNumElements() != 2)
86  break;
87  if ((T->getContainedType(0)->isFloatTy()) &&
88  (T->getContainedType(1)->isFloatTy()))
89  return CFRet;
90  if ((T->getContainedType(0)->isDoubleTy()) &&
91  (T->getContainedType(1)->isDoubleTy()))
92  return CDRet;
93  break;
94  default:
95  break;
96  }
97  return NoFPRet;
98 }
99 
100 //
101 // Parameter type that matter are float, (float, float), (float, double),
102 // double, (double, double), (double, float)
103 //
107 };
108 
109 // which floating point parameter signature variant we are dealing with
110 //
114 
116  switch (F.arg_size()) {
117  case 0:
118  return NoSig;
119  case 1:{
120  TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID();
121  switch (ArgTypeID) {
122  case FloatTyID:
123  return FSig;
124  case DoubleTyID:
125  return DSig;
126  default:
127  return NoSig;
128  }
129  }
130  default: {
131  TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID();
132  TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID();
133  switch(ArgTypeID0) {
134  case FloatTyID: {
135  switch (ArgTypeID1) {
136  case FloatTyID:
137  return FFSig;
138  case DoubleTyID:
139  return FDSig;
140  default:
141  return FSig;
142  }
143  }
144  case DoubleTyID: {
145  switch (ArgTypeID1) {
146  case FloatTyID:
147  return DFSig;
148  case DoubleTyID:
149  return DDSig;
150  default:
151  return DSig;
152  }
153  }
154  default:
155  return NoSig;
156  }
157  }
158  }
159  llvm_unreachable("can't get here");
160 }
161 
162 // Figure out if we need float point based on the function parameters.
163 // We need to move variables in and/or out of floating point
164 // registers because of the ABI
165 //
167  if (F.arg_size() >=1) {
168  Type *ArgType = F.getFunctionType()->getParamType(0);
169  switch (ArgType->getTypeID()) {
170  case Type::FloatTyID:
171  case Type::DoubleTyID:
172  return true;
173  default:
174  break;
175  }
176  }
177  return false;
178 }
179 
181  Type* RetType = F.getReturnType();
182  return whichFPReturnVariant(RetType) != NoFPRet;
183 }
184 
185 static bool needsFPReturnHelper(const FunctionType &FT) {
186  Type* RetType = FT.getReturnType();
187  return whichFPReturnVariant(RetType) != NoFPRet;
188 }
189 
192 }
193 
194 //
195 // We swap between FP and Integer registers to allow Mips16 and Mips32 to
196 // interoperate
197 //
198 static void swapFPIntParams(FPParamVariant PV, Module *M, InlineAsmHelper &IAH,
199  bool LE, bool ToFP) {
200  //LLVMContext &Context = M->getContext();
201  std::string MI = ToFP? "mtc1 ": "mfc1 ";
202  switch (PV) {
203  case FSig:
204  IAH.Out(MI + "$$4,$$f12");
205  break;
206  case FFSig:
207  IAH.Out(MI +"$$4,$$f12");
208  IAH.Out(MI + "$$5,$$f14");
209  break;
210  case FDSig:
211  IAH.Out(MI + "$$4,$$f12");
212  if (LE) {
213  IAH.Out(MI + "$$6,$$f14");
214  IAH.Out(MI + "$$7,$$f15");
215  } else {
216  IAH.Out(MI + "$$7,$$f14");
217  IAH.Out(MI + "$$6,$$f15");
218  }
219  break;
220  case DSig:
221  if (LE) {
222  IAH.Out(MI + "$$4,$$f12");
223  IAH.Out(MI + "$$5,$$f13");
224  } else {
225  IAH.Out(MI + "$$5,$$f12");
226  IAH.Out(MI + "$$4,$$f13");
227  }
228  break;
229  case DDSig:
230  if (LE) {
231  IAH.Out(MI + "$$4,$$f12");
232  IAH.Out(MI + "$$5,$$f13");
233  IAH.Out(MI + "$$6,$$f14");
234  IAH.Out(MI + "$$7,$$f15");
235  } else {
236  IAH.Out(MI + "$$5,$$f12");
237  IAH.Out(MI + "$$4,$$f13");
238  IAH.Out(MI + "$$7,$$f14");
239  IAH.Out(MI + "$$6,$$f15");
240  }
241  break;
242  case DFSig:
243  if (LE) {
244  IAH.Out(MI + "$$4,$$f12");
245  IAH.Out(MI + "$$5,$$f13");
246  } else {
247  IAH.Out(MI + "$$5,$$f12");
248  IAH.Out(MI + "$$4,$$f13");
249  }
250  IAH.Out(MI + "$$6,$$f14");
251  break;
252  case NoSig:
253  return;
254  }
255 }
256 
257 //
258 // Make sure that we know we already need a stub for this function.
259 // Having called needsFPHelperFromSig
260 //
262  const MipsTargetMachine &TM) {
263  // for now we only need them for static relocation
264  if (TM.getRelocationModel() == Reloc::PIC_)
265  return;
266  LLVMContext &Context = M->getContext();
267  bool LE = TM.isLittleEndian();
268  std::string Name = F.getName();
269  std::string SectionName = ".mips16.call.fp." + Name;
270  std::string StubName = "__call_stub_fp_" + Name;
271  //
272  // see if we already have the stub
273  //
274  Function *FStub = M->getFunction(StubName);
275  if (FStub && !FStub->isDeclaration()) return;
276  FStub = Function::Create(F.getFunctionType(),
277  Function::InternalLinkage, StubName, M);
278  FStub->addFnAttr("mips16_fp_stub");
282  FStub->addFnAttr("nomips16");
283  FStub->setSection(SectionName);
284  BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
285  InlineAsmHelper IAH(Context, BB);
286  IAH.Out(".set reorder");
289  swapFPIntParams(PV, M, IAH, LE, true);
290  if (RV != NoFPRet) {
291  IAH.Out("move $$18, $$31");
292  IAH.Out("jal " + Name);
293  } else {
294  IAH.Out("lui $$25,%hi(" + Name + ")");
295  IAH.Out("addiu $$25,$$25,%lo(" + Name + ")" );
296  }
297  switch (RV) {
298  case FRet:
299  IAH.Out("mfc1 $$2,$$f0");
300  break;
301  case DRet:
302  if (LE) {
303  IAH.Out("mfc1 $$2,$$f0");
304  IAH.Out("mfc1 $$3,$$f1");
305  } else {
306  IAH.Out("mfc1 $$3,$$f0");
307  IAH.Out("mfc1 $$2,$$f1");
308  }
309  break;
310  case CFRet:
311  if (LE) {
312  IAH.Out("mfc1 $$2,$$f0");
313  IAH.Out("mfc1 $$3,$$f2");
314  } else {
315  IAH.Out("mfc1 $$3,$$f0");
316  IAH.Out("mfc1 $$3,$$f2");
317  }
318  break;
319  case CDRet:
320  if (LE) {
321  IAH.Out("mfc1 $$4,$$f2");
322  IAH.Out("mfc1 $$5,$$f3");
323  IAH.Out("mfc1 $$2,$$f0");
324  IAH.Out("mfc1 $$3,$$f1");
325 
326  } else {
327  IAH.Out("mfc1 $$5,$$f2");
328  IAH.Out("mfc1 $$4,$$f3");
329  IAH.Out("mfc1 $$3,$$f0");
330  IAH.Out("mfc1 $$2,$$f1");
331  }
332  break;
333  case NoFPRet:
334  break;
335  }
336  if (RV != NoFPRet)
337  IAH.Out("jr $$18");
338  else
339  IAH.Out("jr $$25");
340  new UnreachableInst(Context, BB);
341 }
342 
343 //
344 // Functions that are llvm intrinsics and don't need helpers.
345 //
346 static const char *IntrinsicInline[] = {
347  "fabs", "fabsf",
348  "llvm.ceil.f32", "llvm.ceil.f64",
349  "llvm.copysign.f32", "llvm.copysign.f64",
350  "llvm.cos.f32", "llvm.cos.f64",
351  "llvm.exp.f32", "llvm.exp.f64",
352  "llvm.exp2.f32", "llvm.exp2.f64",
353  "llvm.fabs.f32", "llvm.fabs.f64",
354  "llvm.floor.f32", "llvm.floor.f64",
355  "llvm.fma.f32", "llvm.fma.f64",
356  "llvm.log.f32", "llvm.log.f64",
357  "llvm.log10.f32", "llvm.log10.f64",
358  "llvm.nearbyint.f32", "llvm.nearbyint.f64",
359  "llvm.pow.f32", "llvm.pow.f64",
360  "llvm.powi.f32", "llvm.powi.f64",
361  "llvm.rint.f32", "llvm.rint.f64",
362  "llvm.round.f32", "llvm.round.f64",
363  "llvm.sin.f32", "llvm.sin.f64",
364  "llvm.sqrt.f32", "llvm.sqrt.f64",
365  "llvm.trunc.f32", "llvm.trunc.f64",
366 };
367 
368 static bool isIntrinsicInline(Function *F) {
369  return std::binary_search(std::begin(IntrinsicInline),
371 }
372 //
373 // Returns of float, double and complex need to be handled with a helper
374 // function.
375 //
377  const MipsTargetMachine &TM) {
378  bool Modified = false;
379  LLVMContext &C = M->getContext();
380  Type *MyVoid = Type::getVoidTy(C);
381  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
382  for (BasicBlock::iterator I = BB->begin(), E = BB->end();
383  I != E; ++I) {
384  Instruction &Inst = *I;
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* Helper[NoFPRet] = {
399  "__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",
400  "__mips16_ret_dc"
401  };
402  const char *Name = Helper[RV];
403  AttributeSet 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, nullptr));
419  CallInst::Create(F, Params, "", &Inst );
420  } else if (const CallInst *CI = dyn_cast<CallInst>(I)) {
421  const Value* V = CI->getCalledValue();
422  const Type* T = nullptr;
423  if (V) T = V->getType();
424  const PointerType *PFT=nullptr;
425  if (T) PFT = dyn_cast<PointerType>(T);
426  const FunctionType *FT=nullptr;
427  if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType());
428  Function *F_ = CI->getCalledFunction();
429  if (FT && needsFPReturnHelper(*FT) &&
430  !(F_ && isIntrinsicInline(F_))) {
431  Modified=true;
432  F.addFnAttr("saveS2");
433  }
434  if (F_ && !isIntrinsicInline(F_)) {
435  // pic mode calls are handled by already defined
436  // helper functions
437  if (needsFPReturnHelper(*F_)) {
438  Modified=true;
439  F.addFnAttr("saveS2");
440  }
441  if (TM.getRelocationModel() != Reloc::PIC_ ) {
442  if (needsFPHelperFromSig(*F_)) {
443  assureFPCallStub(*F_, M, TM);
444  Modified=true;
445  }
446  }
447  }
448  }
449  }
450  return Modified;
451 }
452 
454  const MipsTargetMachine &TM) {
455  bool PicMode = TM.getRelocationModel() == Reloc::PIC_;
456  bool LE = TM.isLittleEndian();
457  LLVMContext &Context = M->getContext();
458  std::string Name = F->getName();
459  std::string SectionName = ".mips16.fn." + Name;
460  std::string StubName = "__fn_stub_" + Name;
461  std::string LocalName = "$$__fn_local_" + Name;
462  Function *FStub = Function::Create
463  (F->getFunctionType(),
464  Function::InternalLinkage, StubName, M);
465  FStub->addFnAttr("mips16_fp_stub");
469  FStub->addFnAttr("nomips16");
470  FStub->setSection(SectionName);
471  BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
472  InlineAsmHelper IAH(Context, BB);
473  if (PicMode) {
474  IAH.Out(".set noreorder");
475  IAH.Out(".cpload $$25");
476  IAH.Out(".set reorder");
477  IAH.Out(".reloc 0,R_MIPS_NONE," + Name);
478  IAH.Out("la $$25," + LocalName);
479  }
480  else {
481  IAH.Out("la $$25," + Name);
482  }
483  swapFPIntParams(PV, M, IAH, LE, false);
484  IAH.Out("jr $$25");
485  IAH.Out(LocalName + " = " + Name);
486  new UnreachableInst(FStub->getContext(), BB);
487 }
488 
489 //
490 // remove the use-soft-float attribute
491 //
493  AttributeSet A;
494  DEBUG(errs() << "removing -use-soft-float\n");
496  "use-soft-float", "false");
498  if (F.hasFnAttribute("use-soft-float")) {
499  DEBUG(errs() << "still has -use-soft-float\n");
500  }
502 }
503 
504 
505 //
506 // This pass only makes sense when the underlying chip has floating point but
507 // we are compiling as mips16.
508 // For all mips16 functions (that are not stubs we have already generated), or
509 // declared via attributes as nomips16, we must:
510 // 1) fixup all returns of float, double, single and double complex
511 // by calling a helper function before the actual return.
512 // 2) generate helper functions (stubs) that can be called by mips32
513 // functions that will move parameters passed normally passed in
514 // floating point
515 // registers the soft float equivalents.
516 // 3) in the case of static relocation, generate helper functions so that
517 // mips16 functions can call extern functions of unknown type (mips16 or
518 // mips32).
519 // 4) TBD. For pic, calls to extern functions of unknown type are handled by
520 // predefined helper functions in libc but this work is currently done
521 // during call lowering but it should be moved here in the future.
522 //
523 bool Mips16HardFloat::runOnModule(Module &M) {
524  DEBUG(errs() << "Run on Module Mips16HardFloat\n");
525  bool Modified = false;
526  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
527  if (F->hasFnAttribute("nomips16") &&
528  F->hasFnAttribute("use-soft-float")) {
530  continue;
531  }
532  if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") ||
533  F->hasFnAttribute("nomips16")) continue;
534  Modified |= fixupFPReturnAndCall(*F, &M, TM);
536  if (V != NoSig) {
537  Modified = true;
538  createFPFnStub(F, &M, V, TM);
539  }
540  }
541  return Modified;
542 }
543 
544 
546  return new Mips16HardFloat(TM);
547 }
ReturnInst - Return a value (possibly void), from a function.
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:240
static void swapFPIntParams(FPParamVariant PV, Module *M, InlineAsmHelper &IAH, bool LE, bool ToFP)
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:223
unsigned getStructNumElements() const
Definition: Type.cpp:196
Reloc::Model getRelocationModel() const
Returns the code generation relocation model.
static bool needsFPReturnHelper(Function &F)
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:114
2: 32-bit floating point type
Definition: Type.h:58
iterator end()
Definition: Function.h:459
static void removeUseSoftFloat(Function &F)
Type::TypeID TypeID
FPParamVariant
CallInst - This class represents a function call, abstracting a target machine's calling convention...
bool isDoubleTy() const
isDoubleTy - Return true if this is 'double', a 64-bit IEEE fp type.
Definition: Type.h:146
const_iterator begin(StringRef path)
Get begin iterator over path.
Definition: Path.cpp:232
Type * getReturnType() const
Definition: Function.cpp:233
12: Structures
Definition: Type.h:71
F(f)
Naked function.
Definition: Attributes.h:81
size_t arg_size() const
Definition: Function.cpp:301
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:188
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
static bool needsFPHelperFromSig(Function &F)
TypeID
Definitions of all of the base types for the Type system.
Definition: Type.h:54
Function does not access memory.
Definition: Attributes.h:99
void addFnAttr(Attribute::AttrKind N)
Add function attributes to this function.
Definition: Function.h:187
static bool needsFPStubFromParams(Function &F)
static FPReturnVariant whichFPReturnVariant(Type *T)
FunctionType - Class to represent function types.
Definition: DerivedTypes.h:96
static const char * IntrinsicInline[]
#define T
const Type::TypeID FloatTyID
FPReturnVariant
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
FunctionType::get - This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:361
TypeID getTypeID() const
getTypeID - Return the type id for the type.
Definition: Type.h:134
void removeAttributes(unsigned i, AttributeSet attr)
removes the attributes from the list of attributes.
Definition: Function.cpp:353
iterator begin()
Definition: Function.h:457
Type * getElementType() const
Definition: DerivedTypes.h:323
static bool isIntrinsicInline(Function *F)
PointerType - Class to represent pointers.
Definition: DerivedTypes.h:449
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
Definition: Module.cpp:188
static void assureFPCallStub(Function &F, Module *M, const MipsTargetMachine &TM)
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:131
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
Look up the specified function in the module symbol table.
Definition: Module.cpp:115
LLVM Basic Block Representation.
Definition: BasicBlock.h:65
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:41
Type * getContainedType(unsigned i) const
getContainedType - This method is used to implement the type iterator (defined at the end of the file...
Definition: Type.h:332
UnreachableInst - This function has undefined behavior.
static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM)
bool isFloatTy() const
isFloatTy - Return true if this is 'float', a 32-bit IEEE fp type.
Definition: Type.h:143
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:225
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:103
Function doesn't unwind stack.
Definition: Attributes.h:96
ModulePass * createMips16HardFloatPass(MipsTargetMachine &TM)
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:222
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:285
static FPParamVariant whichFPParamVariantNeeded(Function &F)
AttributeSet addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const
Add an attribute to the attribute set at the given index.
Definition: Attributes.cpp:753
iterator end()
Definition: Module.h:571
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.h:217
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:128
#define I(x, y, z)
Definition: MD5.cpp:54
FunctionType * getFunctionType() const
Definition: Function.cpp:227
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:236
iterator begin()
Definition: Module.h:569
Rename collisions when linking (static functions).
Definition: GlobalValue.h:47
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:28
3: 64-bit floating point type
Definition: Type.h:59
Type * getReturnType() const
Definition: DerivedTypes.h:121
const Type::TypeID DoubleTyID
LLVM Value Representation.
Definition: Value.h:69
#define DEBUG(X)
Definition: Debug.h:92
static cl::opt< bool > Mips16HardFloat("mips16-hard-float", cl::NotHidden, cl::desc("Enable mips16 hard float."), cl::init(false))
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
Definition: Function.h:121
void addAttributes(unsigned i, AttributeSet attrs)
adds the attributes to the list of attributes.
Definition: Function.cpp:347
void setSection(StringRef S)
Definition: Globals.cpp:126
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:265