[llvm-commits] JIT memory manager: Correlate stubs with functions
Evan Cheng
evan.cheng at apple.com
Wed Apr 16 12:50:51 PDT 2008
On Apr 15, 2008, at 6:01 AM, Nicolas Geoffray wrote:
> Hi everyone,
>
> The attached patch adds a new Function parameter to
> startFunctionStub, which is the function that the generated stub
> will call. The motivation behind is that a custom JITMemoryManager
> may want to allocate stubs and functions on a per-module basis. For
> example Module A is given a 20MB, Module B is given 10MB, etc. And
> if a function from A calls a function from B, and a stub is
> generated, it should be allocated on behalf of B.
>
> OK to commit?
Yep.
Evan
>
>
> Thx,
> Nicolas
> Index: include/llvm/Target/TargetJITInfo.h
> ===================================================================
> --- include/llvm/Target/TargetJITInfo.h (revision 49722)
> +++ include/llvm/Target/TargetJITInfo.h (working copy)
> @@ -23,6 +23,7 @@
>
> namespace llvm {
> class Function;
> + class GlobalValue;
> class MachineBasicBlock;
> class MachineCodeEmitter;
> class MachineRelocation;
> @@ -41,8 +42,9 @@
> virtual void replaceMachineCodeForFunction(void *Old, void *New)
> = 0;
>
> /// emitGlobalValueLazyPtr - Use the specified
> MachineCodeEmitter object to
> - /// emit a lazy pointer which contains the address of the
> specified GV.
> - virtual void *emitGlobalValueLazyPtr(void *GV,
> MachineCodeEmitter &MCE) {
> + /// emit a lazy pointer which contains the address of the
> specified ptr.
> + virtual void *emitGlobalValueLazyPtr(const GlobalValue* GV,
> void *ptr,
> + MachineCodeEmitter &MCE) {
> assert(0 && "This target doesn't implement
> emitGlobalValueLazyPtr!");
> return 0;
> }
> @@ -50,7 +52,8 @@
> /// emitFunctionStub - Use the specified MachineCodeEmitter
> object to emit a
> /// small native function that simply calls the function at the
> specified
> /// address. Return the address of the resultant function.
> - virtual void *emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE) {
> + virtual void *emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE) {
> assert(0 && "This target doesn't implement emitFunctionStub!");
> return 0;
> }
> Index: include/llvm/ExecutionEngine/JITMemoryManager.h
> ===================================================================
> --- include/llvm/ExecutionEngine/JITMemoryManager.h (revision 49722)
> +++ include/llvm/ExecutionEngine/JITMemoryManager.h (working copy)
> @@ -74,7 +74,8 @@
> /// thunk for it. The stub should be "close" to the current
> function body,
> /// but should not be included in the 'actualsize' returned by
> /// startFunctionBody.
> - virtual unsigned char *allocateStub(unsigned StubSize, unsigned
> Alignment) =0;
> + virtual unsigned char *allocateStub(const GlobalValue* F,
> unsigned StubSize,
> + unsigned Alignment) =0;
>
>
> /// endFunctionBody - This method is called when the JIT is done
> codegen'ing
> Index: include/llvm/CodeGen/MachineCodeEmitter.h
> ===================================================================
> --- include/llvm/CodeGen/MachineCodeEmitter.h (revision 49722)
> +++ include/llvm/CodeGen/MachineCodeEmitter.h (working copy)
> @@ -82,12 +82,13 @@
> /// have constant pools, the can only use the other emitByte*/
> emitWord*
> /// methods.
> ///
> - virtual void startFunctionStub(unsigned StubSize, unsigned
> Alignment = 1) = 0;
> + virtual void startFunctionStub(const GlobalValue* F, unsigned
> StubSize,
> + unsigned Alignment = 1) = 0;
>
> /// finishFunctionStub - This callback is invoked to terminate a
> function
> /// stub.
> ///
> - virtual void *finishFunctionStub(const Function *F) = 0;
> + virtual void *finishFunctionStub(const GlobalValue* F) = 0;
>
> /// emitByte - This callback is invoked when a byte needs to be
> written to the
> /// output stream.
> Index: lib/CodeGen/ELFWriter.cpp
> ===================================================================
> --- lib/CodeGen/ELFWriter.cpp (revision 49722)
> +++ lib/CodeGen/ELFWriter.cpp (working copy)
> @@ -114,11 +114,12 @@
>
>
> /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
> - void startFunctionStub(unsigned StubSize, unsigned Alignment =
> 1) {
> + void startFunctionStub(const GlobalValue* F, unsigned StubSize,
> + unsigned Alignment = 1) {
> assert(0 && "JIT specific function called!");
> abort();
> }
> - void *finishFunctionStub(const Function *F) {
> + void *finishFunctionStub(const GlobalValue *F) {
> assert(0 && "JIT specific function called!");
> abort();
> return 0;
> Index: lib/CodeGen/MachOWriter.cpp
> ===================================================================
> --- lib/CodeGen/MachOWriter.cpp (revision 49722)
> +++ lib/CodeGen/MachOWriter.cpp (working copy)
> @@ -141,11 +141,12 @@
> virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { }
>
> /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
> - virtual void startFunctionStub(unsigned StubSize, unsigned
> Alignment = 1) {
> + virtual void startFunctionStub(const GlobalValue* F, unsigned
> StubSize,
> + unsigned Alignment = 1) {
> assert(0 && "JIT specific function called!");
> abort();
> }
> - virtual void *finishFunctionStub(const Function *F) {
> + virtual void *finishFunctionStub(const GlobalValue* F) {
> assert(0 && "JIT specific function called!");
> abort();
> return 0;
> Index: lib/Target/PowerPC/PPCJITInfo.h
> ===================================================================
> --- lib/Target/PowerPC/PPCJITInfo.h (revision 49722)
> +++ lib/Target/PowerPC/PPCJITInfo.h (working copy)
> @@ -29,7 +29,8 @@
> is64Bit = tmIs64Bit;
> }
>
> - virtual void *emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE);
> + virtual void *emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE);
> virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn);
> virtual void relocate(void *Function, MachineRelocation *MR,
> unsigned NumRelocs, unsigned char* GOTBase);
> Index: lib/Target/PowerPC/PPCJITInfo.cpp
> ===================================================================
> --- lib/Target/PowerPC/PPCJITInfo.cpp (revision 49722)
> +++ lib/Target/PowerPC/PPCJITInfo.cpp (working copy)
> @@ -15,6 +15,7 @@
> #include "PPCJITInfo.h"
> #include "PPCRelocations.h"
> #include "PPCTargetMachine.h"
> +#include "llvm/Function.h"
> #include "llvm/CodeGen/MachineCodeEmitter.h"
> #include "llvm/Config/alloca.h"
> #include "llvm/Support/Debug.h"
> @@ -338,12 +339,13 @@
> #endif
> }
>
> -void *PPCJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE) {
> +void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE) {
> // If this is just a call to an external function, emit a branch
> instead of a
> // call. The code is the same except for one bit of the last
> instruction.
> if (Fn != (void*)(intptr_t)PPC32CompilationCallback &&
> Fn != (void*)(intptr_t)PPC64CompilationCallback) {
> - MCE.startFunctionStub(7*4);
> + MCE.startFunctionStub(F, 7*4);
> intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
> MCE.emitWordBE(0);
> MCE.emitWordBE(0);
> @@ -354,10 +356,10 @@
> MCE.emitWordBE(0);
> EmitBranchToAt(Addr, (intptr_t)Fn, false, is64Bit);
> SyncICache((void*)Addr, 7*4);
> - return MCE.finishFunctionStub(0);
> + return MCE.finishFunctionStub(F);
> }
>
> - MCE.startFunctionStub(10*4);
> + MCE.startFunctionStub(F, 10*4);
> intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
> if (is64Bit) {
> MCE.emitWordBE(0xf821ffb1); // stdu r1,-80(r1)
> @@ -382,7 +384,7 @@
> MCE.emitWordBE(0);
> EmitBranchToAt(BranchAddr, (intptr_t)Fn, true, is64Bit);
> SyncICache((void*)Addr, 10*4);
> - return MCE.finishFunctionStub(0);
> + return MCE.finishFunctionStub(F);
> }
>
>
> Index: lib/Target/ARM/ARMJITInfo.cpp
> ===================================================================
> --- lib/Target/ARM/ARMJITInfo.cpp (revision 49722)
> +++ lib/Target/ARM/ARMJITInfo.cpp (working copy)
> @@ -15,6 +15,7 @@
> #include "ARMJITInfo.h"
> #include "ARMRelocations.h"
> #include "ARMSubtarget.h"
> +#include "llvm/Function.h"
> #include "llvm/CodeGen/MachineCodeEmitter.h"
> #include "llvm/Config/alloca.h"
> #include <cstdlib>
> @@ -93,20 +94,21 @@
> return ARMCompilationCallback;
> }
>
> -void *ARMJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE) {
> +void *ARMJITInfo::emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE) {
> unsigned addr = (intptr_t)Fn;
> // If this is just a call to an external function, emit a branch
> instead of a
> // call. The code is the same except for one bit of the last
> instruction.
> if (Fn != (void*)(intptr_t)ARMCompilationCallback) {
> // branch to the corresponding function addr
> // the stub is 8-byte size and 4-aligned
> - MCE.startFunctionStub(8, 4);
> + MCE.startFunctionStub(F, 8, 4);
> MCE.emitWordLE(0xE51FF004); // LDR PC, [PC,#-4]
> MCE.emitWordLE(addr); // addr of function
> } else {
> // branch and link to the corresponding function addr
> // the stub is 20-byte size and 4-aligned
> - MCE.startFunctionStub(20, 4);
> + MCE.startFunctionStub(F, 20, 4);
> MCE.emitWordLE(0xE92D4800); // STMFD SP!, [R11, LR]
> MCE.emitWordLE(0xE28FE004); // ADD LR, PC, #4
> MCE.emitWordLE(0xE51FF004); // LDR PC, [PC,#-4]
> @@ -114,7 +116,7 @@
> MCE.emitWordLE(0xE8BD8800); // LDMFD SP!, [R11, PC]
> }
>
> - return MCE.finishFunctionStub(0);
> + return MCE.finishFunctionStub(F);
> }
>
> /// relocate - Before the JIT can run a block of code that has been
> emitted,
> Index: lib/Target/ARM/ARMJITInfo.h
> ===================================================================
> --- lib/Target/ARM/ARMJITInfo.h (revision 49722)
> +++ lib/Target/ARM/ARMJITInfo.h (working copy)
> @@ -34,7 +34,8 @@
> /// emitFunctionStub - Use the specified MachineCodeEmitter
> object to emit a
> /// small native function that simply calls the function at the
> specified
> /// address.
> - virtual void *emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE);
> + virtual void *emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE);
>
> /// getLazyResolverFunction - Expose the lazy resolver to the JIT.
> virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn);
> Index: lib/Target/Alpha/AlphaJITInfo.cpp
> ===================================================================
> --- lib/Target/Alpha/AlphaJITInfo.cpp (revision 49722)
> +++ lib/Target/Alpha/AlphaJITInfo.cpp (working copy)
> @@ -14,6 +14,7 @@
> #define DEBUG_TYPE "jit"
> #include "AlphaJITInfo.h"
> #include "AlphaRelocations.h"
> +#include "llvm/Function.h"
> #include "llvm/CodeGen/MachineCodeEmitter.h"
> #include "llvm/Config/alloca.h"
> #include "llvm/Support/Debug.h"
> @@ -190,16 +191,17 @@
> #endif
> }
>
> -void *AlphaJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE) {
> +void *AlphaJITInfo::emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE) {
> //assert(Fn == AlphaCompilationCallback && "Where are you going?
> \n");
> //Do things in a stupid slow way!
> - MCE.startFunctionStub(19*4);
> + MCE.startFunctionStub(F, 19*4);
> void* Addr = (void*)(intptr_t)MCE.getCurrentPCValue();
> for (int x = 0; x < 19; ++ x)
> MCE.emitWordLE(0);
> EmitBranchToAt(Addr, Fn);
> DOUT << "Emitting Stub to " << Fn << " at [" << Addr << "]\n";
> - return MCE.finishFunctionStub(0);
> + return MCE.finishFunctionStub(F);
> }
>
> TargetJITInfo::LazyResolverFn
> Index: lib/Target/Alpha/AlphaJITInfo.h
> ===================================================================
> --- lib/Target/Alpha/AlphaJITInfo.h (revision 49722)
> +++ lib/Target/Alpha/AlphaJITInfo.h (working copy)
> @@ -29,7 +29,8 @@
> explicit AlphaJITInfo(TargetMachine &tm) : TM(tm)
> { useGOT = true; }
>
> - virtual void *emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE);
> + virtual void *emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE);
> virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn);
> virtual void relocate(void *Function, MachineRelocation *MR,
> unsigned NumRelocs, unsigned char* GOTBase);
> Index: lib/Target/X86/X86JITInfo.h
> ===================================================================
> --- lib/Target/X86/X86JITInfo.h (revision 49722)
> +++ lib/Target/X86/X86JITInfo.h (working copy)
> @@ -14,6 +14,7 @@
> #ifndef X86JITINFO_H
> #define X86JITINFO_H
>
> +#include "llvm/Function.h"
> #include "llvm/Target/TargetJITInfo.h"
>
> namespace llvm {
> @@ -33,13 +34,15 @@
> virtual void replaceMachineCodeForFunction(void *Old, void *New);
>
> /// emitGlobalValueLazyPtr - Use the specified
> MachineCodeEmitter object to
> - /// emit a lazy pointer which contains the address of the
> specified GV.
> - virtual void *emitGlobalValueLazyPtr(void *GV,
> MachineCodeEmitter &MCE);
> + /// emit a lazy pointer which contains the address of the
> specified ptr.
> + virtual void *emitGlobalValueLazyPtr(const GlobalValue* GV,
> void *ptr,
> + MachineCodeEmitter &MCE);
>
> /// emitFunctionStub - Use the specified MachineCodeEmitter
> object to emit a
> /// small native function that simply calls the function at the
> specified
> /// address.
> - virtual void *emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE);
> + virtual void *emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE);
>
> /// getPICJumpTableEntry - Returns the value of the jumptable
> entry for the
> /// specific basic block.
> Index: lib/Target/X86/X86JITInfo.cpp
> ===================================================================
> --- lib/Target/X86/X86JITInfo.cpp (revision 49722)
> +++ lib/Target/X86/X86JITInfo.cpp (working copy)
> @@ -15,6 +15,7 @@
> #include "X86JITInfo.h"
> #include "X86Relocations.h"
> #include "X86Subtarget.h"
> +#include "llvm/Function.h"
> #include "llvm/CodeGen/MachineCodeEmitter.h"
> #include "llvm/Config/alloca.h"
> #include <cstdlib>
> @@ -391,19 +392,21 @@
> return X86CompilationCallback;
> }
>
> -void *X86JITInfo::emitGlobalValueLazyPtr(void *GV,
> MachineCodeEmitter &MCE) {
> +void *X86JITInfo::emitGlobalValueLazyPtr(const GlobalValue* GV,
> void *ptr,
> + MachineCodeEmitter &MCE) {
> #if defined (X86_64_JIT)
> MCE.startFunctionStub(8, 8);
> - MCE.emitWordLE(((unsigned *)&GV)[0]);
> - MCE.emitWordLE(((unsigned *)&GV)[1]);
> + MCE.emitWordLE(((unsigned *)&ptr)[0]);
> + MCE.emitWordLE(((unsigned *)&ptr)[1]);
> #else
> - MCE.startFunctionStub(4, 4);
> - MCE.emitWordLE((intptr_t)GV);
> + MCE.startFunctionStub(GV, 4, 4);
> + MCE.emitWordLE((intptr_t)ptr);
> #endif
> - return MCE.finishFunctionStub(0);
> + return MCE.finishFunctionStub(GV);
> }
>
> -void *X86JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter
> &MCE) {
> +void *X86JITInfo::emitFunctionStub(const Function* F, void *Fn,
> + MachineCodeEmitter &MCE) {
> // Note, we cast to intptr_t here to silence a -pedantic warning
> that
> // complains about casting a function pointer to a normal pointer.
> #if defined (X86_32_JIT) && !defined (_MSC_VER)
> @@ -414,7 +417,7 @@
> #endif
> if (NotCC) {
> #if defined (X86_64_JIT)
> - MCE.startFunctionStub(13, 4);
> + MCE.startFunctionStub(F, 13, 4);
> MCE.emitByte(0x49); // REX prefix
> MCE.emitByte(0xB8+2); // movabsq r10
> MCE.emitWordLE(((unsigned *)&Fn)[0]);
> @@ -423,15 +426,15 @@
> MCE.emitByte(0xFF); // jmpq *r10
> MCE.emitByte(2 | (4 << 3) | (3 << 6));
> #else
> - MCE.startFunctionStub(5, 4);
> + MCE.startFunctionStub(F, 5, 4);
> MCE.emitByte(0xE9);
> MCE.emitWordLE((intptr_t)Fn-MCE.getCurrentPCValue()-4);
> #endif
> - return MCE.finishFunctionStub(0);
> + return MCE.finishFunctionStub(F);
> }
>
> #if defined (X86_64_JIT)
> - MCE.startFunctionStub(14, 4);
> + MCE.startFunctionStub(F, 14, 4);
> MCE.emitByte(0x49); // REX prefix
> MCE.emitByte(0xB8+2); // movabsq r10
> MCE.emitWordLE(((unsigned *)&Fn)[0]);
> @@ -440,14 +443,14 @@
> MCE.emitByte(0xFF); // callq *r10
> MCE.emitByte(2 | (2 << 3) | (3 << 6));
> #else
> - MCE.startFunctionStub(6, 4);
> + MCE.startFunctionStub(F, 6, 4);
> MCE.emitByte(0xE8); // Call with 32 bit pc-rel destination...
>
> MCE.emitWordLE((intptr_t)Fn-MCE.getCurrentPCValue()-4);
> #endif
>
> MCE.emitByte(0xCD); // Interrupt - Just a marker identifying the
> stub!
> - return MCE.finishFunctionStub(0);
> + return MCE.finishFunctionStub(F);
> }
>
> /// getPICJumpTableEntry - Returns the value of the jumptable entry
> for the
> Index: lib/ExecutionEngine/JIT/JITEmitter.cpp
> ===================================================================
> --- lib/ExecutionEngine/JIT/JITEmitter.cpp (revision 49722)
> +++ lib/ExecutionEngine/JIT/JITEmitter.cpp (working copy)
> @@ -175,7 +175,7 @@
>
> // Otherwise, codegen a new stub. For now, the stub will call the
> lazy
> // resolver function.
> - Stub = TheJIT->getJITInfo().emitFunctionStub(Actual,
> + Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual,
> *TheJIT-
> >getCodeEmitter());
>
> if (Actual != (void*)(intptr_t)LazyResolverFn) {
> @@ -204,7 +204,7 @@
> if (LazyPtr) return LazyPtr;
>
> // Otherwise, codegen a new lazy pointer.
> - LazyPtr = TheJIT->getJITInfo().emitGlobalValueLazyPtr(GVAddress,
> + LazyPtr = TheJIT->getJITInfo().emitGlobalValueLazyPtr(GV,
> GVAddress,
> *TheJIT-
> >getCodeEmitter());
>
> DOUT << "JIT: Stub emitted at [" << LazyPtr << "] for GV '"
> @@ -220,7 +220,7 @@
> void *&Stub = ExternalFnToStubMap[FnAddr];
> if (Stub) return Stub;
>
> - Stub = TheJIT->getJITInfo().emitFunctionStub(FnAddr,
> + Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr,
> *TheJIT-
> >getCodeEmitter());
>
> DOUT << "JIT: Stub emitted at [" << Stub
> @@ -503,8 +503,9 @@
> void initJumpTableInfo(MachineJumpTableInfo *MJTI);
> void emitJumpTableInfo(MachineJumpTableInfo *MJTI);
>
> - virtual void startFunctionStub(unsigned StubSize, unsigned
> Alignment = 1);
> - virtual void* finishFunctionStub(const Function *F);
> + virtual void startFunctionStub(const GlobalValue* F, unsigned
> StubSize,
> + unsigned Alignment = 1);
> + virtual void* finishFunctionStub(const GlobalValue *F);
>
> virtual void addRelocation(const MachineRelocation &MR) {
> Relocations.push_back(MR);
> @@ -822,16 +823,17 @@
> }
> }
>
> -void JITEmitter::startFunctionStub(unsigned StubSize, unsigned
> Alignment) {
> +void JITEmitter::startFunctionStub(const GlobalValue* F, unsigned
> StubSize,
> + unsigned Alignment) {
> SavedBufferBegin = BufferBegin;
> SavedBufferEnd = BufferEnd;
> SavedCurBufferPtr = CurBufferPtr;
>
> - BufferBegin = CurBufferPtr = MemMgr->allocateStub(StubSize,
> Alignment);
> + BufferBegin = CurBufferPtr = MemMgr->allocateStub(F, StubSize,
> Alignment);
> BufferEnd = BufferBegin+StubSize+1;
> }
>
> -void *JITEmitter::finishFunctionStub(const Function *F) {
> +void *JITEmitter::finishFunctionStub(const GlobalValue* F) {
> NumBytes += getCurrentPCOffset();
> std::swap(SavedBufferBegin, BufferBegin);
> BufferEnd = SavedBufferEnd;
> Index: lib/ExecutionEngine/JIT/JITMemoryManager.cpp
> ===================================================================
> --- lib/ExecutionEngine/JIT/JITMemoryManager.cpp (revision 49722)
> +++ lib/ExecutionEngine/JIT/JITMemoryManager.cpp (working copy)
> @@ -11,6 +11,7 @@
> //
> //
> =
> =
> =
> ----------------------------------------------------------------------=
> ==//
>
> +#include "llvm/GlobalValue.h"
> #include "llvm/ExecutionEngine/JITMemoryManager.h"
> #include "llvm/Support/Compiler.h"
> #include "llvm/System/Memory.h"
> @@ -265,7 +266,8 @@
>
> void AllocateGOT();
>
> - unsigned char *allocateStub(unsigned StubSize, unsigned
> Alignment);
> + unsigned char *allocateStub(const GlobalValue* F, unsigned
> StubSize,
> + unsigned Alignment);
>
> /// startFunctionBody - When a function starts, allocate a block
> of free
> /// executable memory, returning a pointer to it and its actual
> size.
> @@ -438,7 +440,8 @@
> Blocks.clear();
> }
>
> -unsigned char *DefaultJITMemoryManager::allocateStub(unsigned
> StubSize,
> +unsigned char *DefaultJITMemoryManager::allocateStub(const
> GlobalValue* F,
> + unsigned
> StubSize,
> unsigned
> Alignment) {
> CurStubPtr -= StubSize;
> CurStubPtr = (unsigned char*)(((intptr_t)CurStubPtr) &
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list