diff options
Diffstat (limited to 'include/llvm')
39 files changed, 1235 insertions, 17 deletions
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 2920675231..b8d435ee13 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -94,6 +94,12 @@ namespace llvm { /// default, this is equal to CurrentFnSym. MCSymbol *CurrentFnSymForSize; + /// @LOCALMOD-BEGIN + /// Is the bitcode module a plain object? This is false + /// for shared (pso) and executable (pexe) files. + bool IsPlainObject; + /// @LOCALMOD-END + private: // GCMetadataPrinters - The garbage collection metadata printer table. void *GCMetadataPrinters; // Really a DenseMap. @@ -240,6 +246,18 @@ namespace llvm { // Targets can, or in the case of EmitInstruction, must implement these to // customize output. + // @LOCALMOD-START + /// UseReadOnlyJumpTables - true if JumpTableInfo must be in rodata. + virtual bool UseReadOnlyJumpTables() const { return false; } + /// GetTargetBasicBlockAlign - the target alignment for basic blocks. + virtual unsigned GetTargetBasicBlockAlign() const { return 0; } + /// GetTargetLabelAlign - Get optional alignment for TargetOpcode + /// labels E.g., EH_LABEL. + virtual unsigned GetTargetLabelAlign(const MachineInstr *MI) const { + return 0; + } + // @LOCALMOD-END + /// EmitStartOfAsmFile - This virtual method can be overridden by targets /// that want to emit something at the start of their file. virtual void EmitStartOfAsmFile(Module &) {} @@ -254,7 +272,12 @@ namespace llvm { /// EmitFunctionBodyEnd - Targets can override this to emit stuff after /// the last basic block in the function. - virtual void EmitFunctionBodyEnd() {} + virtual void EmitFunctionBodyEnd() { + // @LOCALMOD-START + unsigned NextFunctionAlignment = GetTargetBasicBlockAlign(); + if (NextFunctionAlignment) EmitAlignment(NextFunctionAlignment); + // @LOCALMOD-END + } /// EmitInstruction - Targets should implement this to emit instructions. virtual void EmitInstruction(const MachineInstr *) { diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index 3afe3095d4..59e7520d24 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -164,6 +164,7 @@ private: SmallVector<uint32_t, 16> UsedRegs; unsigned FirstByValReg; bool FirstByValRegValid; + bool HasByValInRegPosition; // @LOCALMOD -- ARM only: see comment below. protected: ParmContext CallOrPrologue; @@ -311,6 +312,19 @@ public: void clearFirstByValReg() { FirstByValReg = 0; FirstByValRegValid = false; } bool isFirstByValRegValid() const { return FirstByValRegValid; } + // @LOCALMOD-BEGIN + // We disabled the splitting of byval between registers and memory. + // This separate flag indicates that a byval existed. We cannot reuse + // isFirstByValRegValid() because that is already used by the broken + // mechanism of splitting between stack and regs. We should check + // again if this mechanism is still broken later, or try to fix that + // mechanism. + // NOTE: this is only for ARM, so should be refactored. + bool hasByValInRegPosition() const { return HasByValInRegPosition; } + void setHasByValInRegPosition() { HasByValInRegPosition = true; } + void clearHasByValInRegPosition() { HasByValInRegPosition = false; } + // @LOCALMOD-END + ParmContext getCallOrPrologue() const { return CallOrPrologue; } private: diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 5d0a3b4c70..95aafb324d 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -641,6 +641,16 @@ namespace ISD { /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, + // @LOCALMOD-BEGIN + // NACL_* - Native Client instrinsics. + // These correspond to functions in: + // native_client/src/untrusted/nacl/tls_params.h + NACL_TP_TLS_OFFSET, + NACL_TP_TDB_OFFSET, + // Expands to the target architecture enumeration value. + NACL_TARGET_ARCH, + // @LOCALMOD-END + /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. BUILTIN_OP_END diff --git a/include/llvm/CodeGen/IntrinsicLowering.h b/include/llvm/CodeGen/IntrinsicLowering.h index 767b666225..c5ffc7ec0e 100644 --- a/include/llvm/CodeGen/IntrinsicLowering.h +++ b/include/llvm/CodeGen/IntrinsicLowering.h @@ -16,6 +16,7 @@ #ifndef LLVM_CODEGEN_INTRINSICLOWERING_H #define LLVM_CODEGEN_INTRINSICLOWERING_H +#include "llvm/ADT/StringSet.h" // @LOCALMOD #include "llvm/Intrinsics.h" namespace llvm { @@ -26,12 +27,23 @@ namespace llvm { class IntrinsicLowering { const TargetData& TD; - + static StringSet<> FuncNames; // @LOCALMOD + bool Warned; public: explicit IntrinsicLowering(const TargetData &td) : TD(td), Warned(false) {} + /// @LOCALMOD-BEGIN + /// GetFuncNames - Get the names of all functions which may + /// be called by an intrinsic. + static const StringSet<> &GetFuncNames(); + + /// IsCalledByIntrinsic - Returns true if a function may be called + /// by an intrinsic. + static bool IsCalledByIntrinsic(const StringRef &FuncName); + /// @LOCALMOD-END + /// AddPrototypes - This method, if called, causes all of the prototypes /// that might be needed by an intrinsic lowering implementation to be /// inserted into the module specified. diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h index 89f00e91f7..f95b8b6b84 100644 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ b/include/llvm/CodeGen/JITCodeEmitter.h @@ -290,7 +290,7 @@ public: /// getCurrentPCOffset - Return the offset from the start of the emitted /// buffer that we are currently writing to. - uintptr_t getCurrentPCOffset() const { + virtual uintptr_t getCurrentPCOffset() const { // @LOCALMOD return CurBufferPtr-BufferBegin; } @@ -335,6 +335,13 @@ public: /// getLabelLocations - Return the label locations map of the label IDs to /// their address. virtual DenseMap<MCSymbol*, uintptr_t> *getLabelLocations() { return 0; } + + // @LOCALMOD-START + virtual void beginBundleLock() {}; + virtual void endBundleLock() {}; + virtual void alignToBundleBeginning() {}; + virtual void alignToBundleEnd() {}; + // @LOCALMOD-END }; } // End llvm namespace diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 8414c64544..e1911cfd82 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -162,6 +162,12 @@ public: #ifndef NDEBUG IndentLevel = 0; #endif + // @LOCALMOD-BEGIN -- Hack for bug + // http://code.google.com/p/nativeclient/issues/detail?id=2786 + Desc.make_weak(); + InlinedAtLocation.make_weak(); + // @LOCALMOD-END + if (Parent) Parent->addChild(this); } diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index d6d65a24de..b0a70a872e 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -57,6 +57,17 @@ public: virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; + // @LOCALMOD-START + /// getJumpTableIndex - Check if this is a reference to a jump table. + /// If so, return a pointer to the jump table index value that is stored + /// in the constant pool, else return 0. + /// The default behavior is to indicate that the value is not a jump table + /// index. This is used by BranchFolder::runOnMachineFunction() and only in + /// conjunction with ARM targets + /// TODO: this should be cleaned up as it does tripple duty: tester, setter, getter + virtual unsigned *getJumpTableIndex() { return 0; } + // @LOCALMOD-END + /// print - Implement operator<< virtual void print(raw_ostream &O) const = 0; }; diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 654361f9d4..c023d8815b 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -282,6 +282,21 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, return BuildMI(BB, MII, DL, MCID); } +// @LOCALMOD-BEGIN +/// BuildMI - This version of the builder inserts the newly-built +/// instruction before the given position in the given MachineBasicBlock, +/// does NOT take a destination register, and does not add implicit operands. +/// +inline MachineInstrBuilder BuildMI_NoImp(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const MCInstrDesc &MCID) { + MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL, true); + BB.insert(I, MI); + return MachineInstrBuilder(MI); +} +// @LOCALMOD-END + /// BuildMI - This version of the builder inserts the newly-built /// instruction at the end of the given MachineBasicBlock, and does NOT take a /// destination register. diff --git a/include/llvm/CodeGen/MachineRelocation.h b/include/llvm/CodeGen/MachineRelocation.h index 244b466e17..8d71930882 100644 --- a/include/llvm/CodeGen/MachineRelocation.h +++ b/include/llvm/CodeGen/MachineRelocation.h @@ -197,6 +197,14 @@ public: return Offset; } + // @LOCALMOD-START + /// setMachineCodeOffset() - Adjust the offset in the code buffer (this is + /// used when the instruction is moved after emission for bundle alignment) + void setMachineCodeOffset(intptr_t offset) { + Offset = offset; + } + // @LOCALMOD-END + /// getRelocationType - Return the target-specific relocation ID for this /// relocation. unsigned getRelocationType() const { diff --git a/include/llvm/ExecutionEngine/NaClJITMemoryManager.h b/include/llvm/ExecutionEngine/NaClJITMemoryManager.h new file mode 100644 index 0000000000..dcd06627df --- /dev/null +++ b/include/llvm/ExecutionEngine/NaClJITMemoryManager.h @@ -0,0 +1,237 @@ +//=-- NaClJITMemoryManager.h - Interface JIT uses to Allocate Mem -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_EXECUTION_ENGINE_NACL_JIT_MEMMANAGER_H +#define LLVM_EXECUTION_ENGINE_NACL_JIT_MEMMANAGER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +class Function; +class GlobalValue; + +struct SimpleSlab { + uint8_t *address; + size_t size; + uint8_t *next_free; +}; + +struct FreeListNode { + uint8_t *address; + uintptr_t size; + FreeListNode *Prev; + FreeListNode *Next; + FreeListNode *RemoveFromFreeList() { + assert(Next->Prev == this && Prev->Next == this && "Freelist broken!"); + Next->Prev = Prev; + return Prev->Next = Next; + } + void AddToFreeList(FreeListNode *FreeList) { + Next = FreeList; + Prev = FreeList->Prev; + Prev->Next = this; + Next->Prev = this; + } +}; + +class NaClJITMemoryManager : public JITMemoryManager { + // NaCl disallows writing into any code region, and disallows executing any + // data region. Thus we can never get any RWX memory and the the strategy + // used by the other allocators of colocation of allocation metadata + // with the allocated code won't work. + // Currently with NaCl we have one single pool of usable space between the + // text and rodata segments, defined by the linker + // so to support stub allocation in the middle of a function, we allocate + // them in slabs interspersed with the functions. + + static const size_t kStubSlabSize = 16 * 1024; + static const size_t kDataSlabSize = 16 * 1024; + static const size_t kCodeSlabSize = 64 * 1024; + + typedef DenseMap<uint8_t *, size_t> AllocationTable; + + uint8_t *AllocatableRegionStart; + uint8_t *AllocatableRegionLimit; + uint8_t *NextCode; + SimpleSlab CurrentStubSlab; + + // Allocation metadata must be kept separate from code, so the free list is + // allocated with new rather than being a header in the code blocks + FreeListNode *CodeFreeListHead; + FreeListNode *CurrentCodeBlock; + // Mapping from pointer to allocated function, to size of allocation + AllocationTable AllocatedFunctions; + + // Since Exception tables are allocated like functions (i.e. we don't know + // ahead of time how large they are) we use the same allocation method for + // simplicity even though it's not strictly necessary to separate the + // allocation metadata from the allocated data. + FreeListNode *DataFreeListHead; + FreeListNode *CurrentDataBlock; + AllocationTable AllocatedTables; + BumpPtrAllocator DataAllocator; + + uint8_t *GOTBase; // Target Specific reserved memory + + FreeListNode *allocateCodeSlab(size_t MinSize); + FreeListNode *allocateDataSlab(size_t MinSize); + SimpleSlab allocateStubSlab(size_t MinSize); + + // Functions for allocations using one of the free lists + void InitFreeList(FreeListNode **Head); + void DestroyFreeList(FreeListNode *Head); + FreeListNode *FreeListAllocate(uintptr_t &ActualSize, FreeListNode *Head, + FreeListNode * (NaClJITMemoryManager::*allocate)(size_t)); + void FreeListFinishAllocation(FreeListNode *Block, FreeListNode *Head, + uint8_t *AllocationStart, uint8_t *AllocationEnd, AllocationTable &table); + void FreeListDeallocate(FreeListNode *Head, AllocationTable &Table, + void *Body); + public: + // TODO(dschuff): how to find the real value? is it a flag? + static const int kBundleSize = 32; + static const intptr_t kJumpMask = -32; + NaClJITMemoryManager(); + virtual ~NaClJITMemoryManager(); + static inline bool classof(const JITMemoryManager*) { return true; } + + /// setMemoryWritable - No-op on NaCl - code is never writable + virtual void setMemoryWritable() {} + + /// setMemoryExecutable - No-op on NaCl - data is never executable + virtual void setMemoryExecutable() {} + + /// setPoisonMemory - No-op on NaCl - nothing unvalidated is ever executable + virtual void setPoisonMemory(bool poison) {} + + /// getPointerToNamedFunction - This method returns the address of the + /// specified function. As such it is only useful for resolving library + /// symbols, not code generated symbols. + /// + /// If AbortOnFailure is false and no function with the given name is + /// found, this function silently returns a null pointer. Otherwise, + /// it prints a message to stderr and aborts. + /// + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) ; + + //===--------------------------------------------------------------------===// + // Global Offset Table Management + //===--------------------------------------------------------------------===// + + /// AllocateGOT - If the current table requires a Global Offset Table, this + /// method is invoked to allocate it. This method is required to set HasGOT + /// to true. + virtual void AllocateGOT(); + + /// getGOTBase - If this is managing a Global Offset Table, this method should + /// return a pointer to its base. + virtual uint8_t *getGOTBase() const { + return GOTBase; + } + + //===--------------------------------------------------------------------===// + // Main Allocation Functions + //===--------------------------------------------------------------------===// + + /// startFunctionBody - When we start JITing a function, the JIT calls this + /// method to allocate a block of free RWX memory, which returns a pointer to + /// it. If the JIT wants to request a block of memory of at least a certain + /// size, it passes that value as ActualSize, and this method returns a block + /// with at least that much space. If the JIT doesn't know ahead of time how + /// much space it will need to emit the function, it passes 0 for the + /// ActualSize. In either case, this method is required to pass back the size + /// of the allocated block through ActualSize. The JIT will be careful to + /// not write more than the returned ActualSize bytes of memory. + virtual uint8_t *startFunctionBody(const Function *F, + uintptr_t &ActualSize); + + /// allocateStub - This method is called by the JIT to allocate space for a + /// function stub (used to handle limited branch displacements) while it is + /// JIT compiling a function. For example, if foo calls bar, and if bar + /// either needs to be lazily compiled or is a native function that exists too + /// far away from the call site to work, this method will be used to make a + /// 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 uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment); + + /// endFunctionBody - This method is called when the JIT is done codegen'ing + /// the specified function. At this point we know the size of the JIT + /// compiled function. This passes in FunctionStart (which was returned by + /// the startFunctionBody method) and FunctionEnd which is a pointer to the + /// actual end of the function. This method should mark the space allocated + /// and remember where it is in case the client wants to deallocate it. + virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, + uint8_t *FunctionEnd); + + /// allocateCodeSection - Allocate a memory block of (at least) the given + /// size suitable for executable code. The SectionID is a unique identifier + /// assigned by the JIT and passed through to the memory manager for + /// the instance class to use if it needs to communicate to the JIT about + /// a given section after the fact. + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + /// allocateDataSection - Allocate a memory block of (at least) the given + /// size suitable for data. The SectionID is a unique identifier + /// assigned by the JIT and passed through to the memory manager for + /// the instance class to use if it needs to communicate to the JIT about + /// a given section after the fact. + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + /// allocateSpace - Allocate a memory block of the given size. This method + /// cannot be called between calls to startFunctionBody and endFunctionBody. + virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment); + + /// allocateGlobal - Allocate memory for a global. + virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment); + + /// deallocateFunctionBody - Free the specified function body. The argument + /// must be the return value from a call to startFunctionBody() that hasn't + /// been deallocated yet. This is never called when the JIT is currently + /// emitting a function. + virtual void deallocateFunctionBody(void *Body); + + /// startExceptionTable - When we finished JITing the function, if exception + /// handling is set, we emit the exception table. + virtual uint8_t* startExceptionTable(const Function* F, + uintptr_t &ActualSize); + + /// endExceptionTable - This method is called when the JIT is done emitting + /// the exception table. + virtual void endExceptionTable(const Function *F, uint8_t *TableStart, + uint8_t *TableEnd, uint8_t* FrameRegister); + + /// deallocateExceptionTable - Free the specified exception table's memory. + /// The argument must be the return value from a call to startExceptionTable() + /// that hasn't been deallocated yet. This is never called when the JIT is + /// currently emitting an exception table. + virtual void deallocateExceptionTable(void *ET); + + virtual size_t GetDefaultCodeSlabSize() { + return kCodeSlabSize; + } + virtual size_t GetDefaultDataSlabSize() { + return kDataSlabSize; + } + virtual size_t GetDefaultStubSlabSize() { + return kStubSlabSize; + } + +}; + +} + +#endif // LLVM_EXECUTION_ENGINE_NACL_JIT_MEMMANAGER_H diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h index 58d02576c1..bd193b97c9 100644 --- a/include/llvm/GlobalValue.h +++ b/include/llvm/GlobalValue.h @@ -76,6 +76,26 @@ public: removeDeadConstantUsers(); // remove any dead constants using this. } + // @LOCALMOD-BEGIN + /// Set the symbol version for this definition. + void setVersionDef(StringRef Version, bool IsDefault); + + /// Set the symbol version and dynamic source file (soname) + /// for this exterally provided global. + void setNeeded(StringRef Version, StringRef DynFile); + + /// Get the name of this symbol without the version suffix. + StringRef getUnversionedName() const; + + /// Get the version of this symbol. + /// Returns an empty string if the symbol is unversioned. + StringRef getVersion() const; + + /// Returns true if this is the default version of the symbol. + /// This may only be called if the symbol is versioned. + bool isDefaultVersion() const; + // @LOCALMOD-END + unsigned getAlignment() const { return (1u << Alignment) >> 1; } diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 76c22b0fb8..4c93d480dd 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -261,6 +261,7 @@ void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); +void initializeNaClCcRewritePass(PassRegistry&); // @LOCALMOD } #endif diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 804db49556..d960f8c789 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -457,6 +457,32 @@ def int_convertus : Intrinsic<[llvm_anyint_ty], def int_convertuu : Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +// @LOCALMOD-BEGIN +//===----------------------- Native Client Intrinsics ---------------------===// +// TODO(sehr): conditionalize this on IsNaCl64 | IsNaCl32 | IsNaClArm. +// The expansions of these are in lib/Target/X86/X86InstrNacl.{td, cpp} and +// lib/Target/ARM/ARMInstrInfo.td. +def int_nacl_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_ptr_ty]>, + GCCBuiltin<"__builtin_nacl_setjmp">; +def int_nacl_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>, + GCCBuiltin<"__builtin_nacl_longjmp">; + +// The following intrinsics provide target-specific implementations of +// the interface in native_client/src/untrusted/nacl/tls_params.h. +// The intrinsic names are basically the functions there without the +// leading underscores. +def int_nacl_tp_tls_offset : Intrinsic<[llvm_i32_ty], [llvm_i32_ty]>, + GCCBuiltin<"__builtin_nacl_tp_tls_offset">; +def int_nacl_tp_tdb_offset : Intrinsic<[llvm_i32_ty], [llvm_i32_ty]>, + GCCBuiltin<"__builtin_nacl_tp_tdb_offset">; + +// The following intrinsic provides a target-specific constant value to +// indicate the target platform compiled to. The enum values are enumerated +// pnaclintrin.h. +def int_nacl_target_arch : Intrinsic<[llvm_i32_ty], []>, + GCCBuiltin<"__builtin_nacl_target_arch">; +// @LOCALMOD-END + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 348a5f52d2..ebe5542555 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -25,6 +25,7 @@ class MCInst; class MCInstFragment; class MCObjectWriter; class MCSection; +class MCStreamer; class MCValue; class raw_ostream; |