llvm.org GIT mirror llvm / 46fa139
Support for allocation of TLS variables in the JIT. Allocation of a global variable is moved to the execution engine. The JIT calls the TargetJITInfo to allocate thread local storage. Currently, only linux/x86 knows how to allocate thread local global variables. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58142 91177308-0d34-0410-b5e6-96231b3b80d8 Nicolas Geoffray 11 years ago
7 changed file(s) with 74 addition(s) and 16 deletion(s). Raw diff Collapse all Expand all
7575 void setTargetData(const TargetData *td) {
7676 TD = td;
7777 }
78
79 /// getMemoryforGV - Allocate memory for a global variable.
80 virtual char* getMemoryForGV(const GlobalVariable* GV);
7881
7982 // To avoid having libexecutionengine depend on the JIT and interpreter
8083 // libraries, the JIT and Interpreter set these functions to ctor pointers
9292 unsigned NumRelocs, unsigned char* GOTBase) {
9393 assert(NumRelocs == 0 && "This target does not have relocations!");
9494 }
95
96
97 /// allocateThreadLocalMemory - Each target has its own way of
98 /// handling thread local variables. This method returns a value only
99 /// meaningful to the target.
100 virtual char* allocateThreadLocalMemory(size_t size) {
101 assert(0 && "This target does not implement thread local storage!");
102 }
95103
96104 /// needsGOT - Allows a target to specify that it would like the
97105 // JIT to manage a GOT for it.
4949 clearAllGlobalMappings();
5050 for (unsigned i = 0, e = Modules.size(); i != e; ++i)
5151 delete Modules[i];
52 }
53
54 char* ExecutionEngine::getMemoryForGV(const GlobalVariable* GV) {
55 const Type *ElTy = GV->getType()->getElementType();
56 size_t GVSize = (size_t)getTargetData()->getABITypeSize(ElTy);
57 return new char[GVSize];
5258 }
5359
5460 /// removeModuleProvider - Remove a ModuleProvider from the list of modules.
872878 /// their initializers into the memory.
873879 ///
874880 void ExecutionEngine::emitGlobals() {
875 const TargetData *TD = getTargetData();
876881
877882 // Loop over all of the global variables in the program, allocating the memory
878883 // to hold them. If there is more than one module, do a prepass over globals
933938 }
934939
935940 if (!I->isDeclaration()) {
936 // Get the type of the global.
937 const Type *Ty = I->getType()->getElementType();
938
939 // Allocate some memory for it!
940 unsigned Size = TD->getABITypeSize(Ty);
941 addGlobalMapping(I, new char[Size]);
941 addGlobalMapping(I, getMemoryForGV(I));
942942 } else {
943943 // External variable reference. Try to use the dynamic loader to
944944 // get a pointer to it.
990990 void *GA = getPointerToGlobalIfAvailable(GV);
991991 DOUT << "Global '" << GV->getName() << "' -> " << GA << "\n";
992992
993 if (GA == 0) {
994 // If it's not already specified, allocate memory for the global.
995 GA = getMemoryForGV(GV);
996 addGlobalMapping(GV, GA);
997 }
998
999 // Don't initialize if it's thread local, let the client do it.
1000 if (!GV->isThreadLocal())
1001 InitializeMemory(GV->getInitializer(), GA);
1002
9931003 const Type *ElTy = GV->getType()->getElementType();
9941004 size_t GVSize = (size_t)getTargetData()->getABITypeSize(ElTy);
995 if (GA == 0) {
996 // If it's not already specified, allocate memory for the global.
997 GA = new char[GVSize];
998 addGlobalMapping(GV, GA);
999 }
1000
1001 InitializeMemory(GV->getInitializer(), GA);
10021005 NumInitBytes += (unsigned)GVSize;
10031006 ++NumGlobals;
10041007 }
561561 const Type *GlobalType = GV->getType()->getElementType();
562562 size_t S = getTargetData()->getABITypeSize(GlobalType);
563563 size_t A = getTargetData()->getPreferredAlignment(GV);
564 Ptr = MCE->allocateSpace(S, A);
564 if (GV->isThreadLocal()) {
565 MutexGuard locked(lock);
566 Ptr = TJI.allocateThreadLocalMemory(S);
567 } else {
568 Ptr = MCE->allocateSpace(S, A);
569 }
565570 addGlobalMapping(GV, Ptr);
566571 EmitGlobalVariable(GV);
567572 }
593598 return Addr;
594599 }
595600
601 /// getMemoryForGV - This method abstracts memory allocation of global
602 /// variable so that the JIT can allocate thread local variables depending
603 /// on the target.
604 ///
605 char* JIT::getMemoryForGV(const GlobalVariable* GV) {
606 const Type *ElTy = GV->getType()->getElementType();
607 size_t GVSize = (size_t)getTargetData()->getABITypeSize(ElTy);
608 if (GV->isThreadLocal()) {
609 MutexGuard locked(lock);
610 return TJI.allocateThreadLocalMemory(GVSize);
611 } else {
612 return new char[GVSize];
613 }
614 }
133133 private:
134134 static MachineCodeEmitter *createEmitter(JIT &J, JITMemoryManager *JMM);
135135 void runJITOnFunction (Function *F);
136
137 protected:
138
139 /// getMemoryforGV - Allocate memory for a global variable.
140 virtual char* getMemoryForGV(const GlobalVariable* GV);
141
136142 };
137143
138144 } // End llvm namespace
517517 }
518518 }
519519 }
520
521 char* X86JITInfo::allocateThreadLocalMemory(size_t size) {
522 #if defined(X86_32_JIT) && !defined(__APPLE__) && !defined(_MSC_VER)
523 TLSOffset -= size;
524 return TLSOffset;
525 #else
526 assert(0 && "Cannot allocate thread local storage on this arch!\n");
527 return 0;
528 #endif
529 }
2222 class X86JITInfo : public TargetJITInfo {
2323 X86TargetMachine &TM;
2424 intptr_t PICBase;
25 char* TLSOffset;
2526 public:
26 explicit X86JITInfo(X86TargetMachine &tm) : TM(tm) {useGOT = 0;}
27 explicit X86JITInfo(X86TargetMachine &tm) : TM(tm) {
28 useGOT = 0;
29 TLSOffset = 0;
30 }
2731
2832 /// replaceMachineCodeForFunction - Make it so that calling the function
2933 /// whose machine code is at OLD turns into a call to NEW, perhaps by
5559 /// referenced global symbols.
5660 virtual void relocate(void *Function, MachineRelocation *MR,
5761 unsigned NumRelocs, unsigned char* GOTBase);
62
63 /// allocateThreadLocalMemory - Each target has its own way of
64 /// handling thread local variables. This method returns a value only
65 /// meaningful to the target.
66 virtual char* allocateThreadLocalMemory(size_t size);
5867
5968 /// setPICBase / getPICBase - Getter / setter of PICBase, used to compute
6069 /// PIC jumptable entry.