aboutsummaryrefslogtreecommitdiff
path: root/include/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm')
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h25
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h14
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h10
-rw-r--r--include/llvm/CodeGen/IntrinsicLowering.h14
-rw-r--r--include/llvm/CodeGen/JITCodeEmitter.h9
-rw-r--r--include/llvm/CodeGen/LexicalScopes.h6
-rw-r--r--include/llvm/CodeGen/MachineConstantPool.h11
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h15
-rw-r--r--include/llvm/CodeGen/MachineRelocation.h8
-rw-r--r--include/llvm/ExecutionEngine/NaClJITMemoryManager.h237
-rw-r--r--include/llvm/GlobalValue.h20
-rw-r--r--include/llvm/InitializePasses.h1
-rw-r--r--include/llvm/Intrinsics.td26
-rw-r--r--include/llvm/MC/MCAsmBackend.h18
-rw-r--r--include/llvm/MC/MCAsmInfo.h15
-rw-r--r--include/llvm/MC/MCAsmLayout.h5
-rw-r--r--include/llvm/MC/MCAssembler.h128
-rw-r--r--include/llvm/MC/MCELFObjectWriter.h6
-rw-r--r--include/llvm/MC/MCObjectStreamer.h8
-rw-r--r--include/llvm/MC/MCStreamer.h21
-rw-r--r--include/llvm/Module.h54
-rw-r--r--include/llvm/Support/ELF.h1
-rw-r--r--include/llvm/Support/ValueHandle.h14
-rw-r--r--include/llvm/Support/support_macros.h25
-rw-r--r--include/llvm/Support/system_error.h2
-rw-r--r--include/llvm/Target/Target.td34
-rw-r--r--include/llvm/Target/TargetFrameLowering.h19
-rw-r--r--include/llvm/Target/TargetJITInfo.h19
-rw-r--r--include/llvm/Target/TargetLowering.h12
-rw-r--r--include/llvm/Target/TargetOpcodes.h9
-rw-r--r--include/llvm/Target/TargetOptions.h6
-rw-r--r--include/llvm/Transforms/Scalar.h2
-rw-r--r--include/llvm/Value.h6
-rw-r--r--include/llvm/Wrap/BCHeaderField.h106
-rw-r--r--include/llvm/Wrap/bitcode_wrapperer.h192
-rw-r--r--include/llvm/Wrap/file_wrapper_input.h48
-rw-r--r--include/llvm/Wrap/file_wrapper_output.h34
-rw-r--r--include/llvm/Wrap/wrapper_input.h38
-rw-r--r--include/llvm/Wrap/wrapper_output.h34
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;
@@ -150,6 +151,23 @@ public:
/// handleAssemblerFlag - Handle any target-specific assembler flags.
/// By default, do nothing.
virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}
+
+ // @LOCALMOD-BEGIN
+ /// getBundleSize - Return the size (in bytes) of code bundling units
+ /// for this target. If 0, bundling is disabled. This is used exclusively
+ /// for Native Client.
+ virtual unsigned getBundleSize() const {
+ return 0;
+ }
+
+ /// CustomExpandInst -
+ /// If the MCInst instruction has a custom expansion, write it to the
+ /// MCStreamer 'Out'. This can be used to perform "last minute" rewrites of
+ /// MCInst instructions for emission.
+ virtual bool CustomExpandInst(const MCInst &Inst, MCStreamer &Out) const {
+ return false;
+ }
+ // @LOCALMOD-END
};
} // End llvm namespace
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 97aad71fd9..29ec1020c3 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -48,6 +48,14 @@ namespace llvm {
/// Default is 4.
unsigned PointerSize;
+ /// @LOCALMOD-BEGIN
+ /// TODO(pdox): Before upstreaming this, make sure every target backend
+ /// sets it correctly.
+ /// StackSlotSize - Stack slot size in bytes.
+ /// Default is 4.
+ unsigned StackSlotSize;
+ /// @LOCALMOD-END
+
/// IsLittleEndian - True if target is little endian.
/// Default is true.
bool IsLittleEndian;
@@ -340,6 +348,13 @@ namespace llvm {
return PointerSize;
}
+ /// @LOCALMOD-BEGIN
+ /// getStackSlotSize - Get the stack slot size in bytes.
+ unsigned getStackSlotSize() const {
+ return StackSlotSize;
+ }
+ /// @LOCALMOD-END
+
/// islittleendian - True if the target is little endian.
bool isLittleEndian() const {
return IsLittleEndian;
diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h
index cf79216d07..fdded4ffa7 100644
--- a/include/llvm/MC/MCAsmLayout.h
+++ b/include/llvm/MC/MCAsmLayout.h
@@ -80,6 +80,11 @@ public:
/// \brief Get the offset of the given fragment inside its containing section.
uint64_t getFragmentOffset(const MCFragment *F) const;
+ // @LOCALMOD-BEGIN
+ /// \brief Get the bundle padding of the given fragment.
+ uint8_t getFragmentPadding(const MCFragment *F) const;
+ // @LOCALMOD-END
+
/// @}
/// @name Utility Functions
/// @{
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 83c01ec5b9..6fc685cb33 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -52,11 +52,39 @@ public:
FT_Org,
FT_Dwarf,
FT_DwarfFrame,
- FT_LEB
+ FT_LEB,
+ FT_Tiny // @LOCALMOD
};
+ // @LOCALMOD-BEGIN
+ enum BundleAlignType {
+ BundleAlignNone = 0,
+ BundleAlignStart = 1,
+ BundleAlignEnd = 2
+ };
+ // @LOCALMOD-END
+
private:
- FragmentType Kind;
+ // @LOCALMOD-BEGIN
+ // Try to compress the layout of MCFragment by:
+ // 1) Making Kind, the bundling flags, and BundlePadding fit in 32 bits.
+ // 2) Move LayoutOrder to fit in the hole left by aligning for 64 bits.
+
+ FragmentType Kind : 4;
+
+ BundleAlignType BundleAlign : 2;
+ bool BundleGroupStart : 1;
+ bool BundleGroupEnd : 1;
+
+ /// BundlePadding - The computed padding for this fragment. This is ~0
+ /// until initialized.
+ uint8_t BundlePadding;
+
+ /// LayoutOrder - The layout order of this fragment.
+ unsigned LayoutOrder;
+
+ // @LOCALMOD-END
+
/// Parent - The data for the section this fragment is in.
MCSectionData *Parent;
@@ -75,9 +103,6 @@ private:
/// initialized.
uint64_t Offset;
- /// LayoutOrder - The layout order of this fragment.
- unsigned LayoutOrder;
-
/// @}
protected:
@@ -99,14 +124,46 @@ public:
unsigned getLayoutOrder() const { return LayoutOrder; }
void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
+ // @LOCALMOD-BEGIN
+ bool isBundleGroupStart() const { return BundleGroupStart; }
+ void setBundleGroupStart(bool Value) { BundleGroupStart = Value; }
+
+ bool isBundleGroupEnd() const { return BundleGroupEnd; }
+ void setBundleGroupEnd(bool Value) { BundleGroupEnd = Value; }
+
+ BundleAlignType getBundleAlign() const { return BundleAlign; }
+ void setBundleAlign(BundleAlignType Value) { BundleAlign = Value; }
+ // @LOCALMOD-END
+
static bool classof(const MCFragment *O) { return true; }
void dump();
};
+// @LOCALMOD-BEGIN
+// This is just a tiny data fragment with no fixups.
+// (To help with memory usage)
+class MCTinyFragment : public MCFragment {
+ private:
+ SmallString<6> Contents;
+
+ public:
+
+ MCTinyFragment(MCSectionData *SD = 0) : MCFragment(FT_Tiny, SD) {}
+
+ SmallString<6> &getContents() { return Contents; }
+ const SmallString<6> &getContents() const { return Contents; }
+
+ static bool classof(const MCFragment *F) {
+ return F->getKind() == MCFragment::FT_Tiny;
+ }
+ static bool classof(const MCTinyFragment *) { return true; }
+};
+// @LOCALMOD-END
+
class MCDataFragment : public MCFragment {
virtual void anchor();
- SmallString<32> Contents;
+ SmallString<6> Contents; // @LOCALMOD: Memory efficiency
/// Fixups - The list of fixups in this fragment.
std::vector<MCFixup> Fixups;
@@ -121,8 +178,8 @@ public:
/// @name Accessors
/// @{
- SmallString<32> &getContents() { return Contents; }
- const SmallString<32> &getContents() const { return Contents; }
+ SmallString<6> &getContents() { return Contents; } // @LOCALMOD
+ const SmallString<6> &getContents() const { return Contents; } // @LOCALMOD
/// @}
/// @name Fixup Access
@@ -474,6 +531,29 @@ private:
/// it.
unsigned HasInstructions : 1;
+ // @LOCALMOD-BEGIN
+ bool BundlingEnabled : 1;
+ bool BundleLocked : 1;
+
+ // Because ".bundle_lock" occurs before the fragment it applies to exists,
+ // we need to keep this flag around so we know to mark the next fragment
+ // as the start of a bundle group. A similar flag is not necessary for the
+ // last fragment, because when a .bundle_unlock occurs, the last fragment
+ // in the group already exists and can be marked directly.
+ bool BundleGroupFirstFrag : 1;
+
+ typedef MCFragment::BundleAlignType BundleAlignType;
+ BundleAlignType BundleAlignNext : 2;
+
+ // Optimization to reduce the number of fragments generated (for memory
+ // savings). Keep track of when we know the offset of the next point to
+ // emit an instruction. If we know the offset from a known alignment point,
+ // we can just append to the previous fragment.
+ bool BundleOffsetKnown : 1;
+ unsigned BundleSize;
+ unsigned BundleOffset;
+ // @LOCALMOD-END
+
/// @}
public:
@@ -495,6 +575,25 @@ public:
unsigned getLayoutOrder() const { return LayoutOrder; }
void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
+ // @LOCALMOD-BEGIN
+ bool isBundlingEnabled() const { return BundlingEnabled; }
+
+ bool isBundleLocked() const { return BundleLocked; }
+ void setBundleLocked(bool Value) { BundleLocked = Value; }
+
+ bool isBundleGroupFirstFrag() const { return BundleGroupFirstFrag; }
+ void setBundleGroupFirstFrag(bool Value) { BundleGroupFirstFrag = Value; }
+
+
+ BundleAlignType getBundleAlignNext() const { return BundleAlignNext; }
+ void setBundleAlignNext(BundleAlignType Value) { BundleAlignNext = Value; }
+
+ void MarkBundleOffsetUnknown();
+ bool ShouldCreateNewFragment(size_t Size);
+ void UpdateBundleOffset(size_t Size);
+ void AlignBundleOffsetTo(size_t AlignBase);
+ // @LOCALMOD-END
+
/// @name Fragment Access
/// @{
@@ -753,6 +852,13 @@ private:
bool fragmentNeedsRelaxation(const MCInstFragment *IF,
const MCAsmLayout &Layout) const;
+ // @LOCALMOD-BEGIN
+ uint8_t ComputeBundlePadding(const MCAsmLayout &Layout,
+ MCFragment *F,
+ uint64_t FragmentOffset) const;
+ // @LOCALMOD-END
+
+
/// layoutOnce - Perform one layout iteration and return true if any offsets
/// were adjusted.
bool layoutOnce(MCAsmLayout &Layout);
@@ -819,6 +925,12 @@ public:
MCAsmBackend &getBackend() const { return Backend; }
+ // @LOCALMOD-BEGIN
+ uint64_t getBundleSize() const;
+ uint64_t getBundleMask() const;
+ // @LOCALMOD-END
+
+
MCCodeEmitter &getEmitter() const { return Emitter; }
MCObjectWriter &getWriter() const { return Writer; }
diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h
index abbe188fe8..688c8a9575 100644
--- a/include/llvm/MC/MCELFObjectWriter.h
+++ b/include/llvm/MC/MCELFObjectWriter.h
@@ -69,6 +69,12 @@ public:
return ELF::ELFOSABI_FREEBSD;
case Triple::Linux:
return ELF::ELFOSABI_LINUX;
+ // @LOCALMOD-BEGIN
+ // This shouldn't be needed anymore (sel_ldr doesn't check for it),
+ // but removing it may require some changes in binutils also.
+ case Triple::NativeClient:
+ return ELF::ELFOSABI_NACL;
+ // @LOCALMOD-END
default:
return ELF::ELFOSABI_NONE;
}
diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h
index b59b76c2be..466773bc0a 100644
--- a/include/llvm/MC/MCObjectStreamer.h
+++ b/include/llvm/MC/MCObjectStreamer.h
@@ -68,6 +68,14 @@ public:
unsigned AddrSpace);
virtual void EmitULEB128Value(const MCExpr *Value);
virtual void EmitSLEB128Value(const MCExpr *Value);
+
+ // @LOCALMOD-BEGIN
+ void EmitBundleLock();
+ void EmitBundleUnlock();
+ void EmitBundleAlignStart();
+ void EmitBundleAlignEnd();
+ // @LOCALMOD-END
+
virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
virtual void ChangeSection(const MCSection *Section);
virtual void EmitInstruction(const MCInst &Inst);
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 44698989c1..ad30b9ca60 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -467,6 +467,27 @@ namespace llvm {
/// @}
+ // @LOCALMOD-BEGIN
+ /// @name Bundling Directives
+ /// @{
+
+ /// EmitBundleLock - Begin a group of instructions which cannot
+ /// cross a bundle boundary.
+ virtual void EmitBundleLock() = 0;
+
+ /// EmitBundleUnlock - End a bundle-locked group of instructions.
+ virtual void EmitBundleUnlock() = 0;
+
+ /// EmitBundleAlignStart - Guarantee that the next instruction or
+ /// bundle-locked group starts at the beginning of a bundle.
+ virtual void EmitBundleAlignStart() = 0;
+
+ /// EmitBundleAlignEnd - Guarantee that the next instruction or
+ /// bundle-locked group finishes at the end of a bundle.
+ virtual void EmitBundleAlignEnd() = 0;
+ /// @}
+ // @LOCALMOD-END
+
/// EmitFileDirective - Switch to a new logical file. This is used to
/// implement the '.file "foo.c"' assembler directive.
virtual void EmitFileDirective(StringRef Filename) = 0;
diff --git a/include/llvm/Module.h b/include/llvm/Module.h
index e6303ac775..13b56433dc 100644
--- a/include/llvm/Module.h
+++ b/include/llvm/Module.h
@@ -186,6 +186,22 @@ public:
: Behavior(B), Key(K), Val(V) {}
};
+ /// @LOCALMOD-BEGIN
+ /// An enumeration for describing the module format
+ enum OutputFormat {
+ ObjectOutputFormat,
+ SharedOutputFormat,
+ ExecutableOutputFormat
+ };
+
+ /// A structure describing the symbols needed from an external file.
+ struct NeededRecord {
+ std::string DynFile; // Source file (soname)
+ std::vector<std::string> Symbols; // List of symbol names
+ // (with version suffix)
+ };
+ /// @LOCALMOD-END
+
/// @}
/// @name Member Variables
/// @{
@@ -203,6 +219,9 @@ private:
std::string ModuleID; ///< Human readable identifier for the module
std::string TargetTriple; ///< Platform target triple Module compiled on
std::string DataLayout; ///< Target data description
+ // @LOCALMOD-BEGIN
+ mutable std::string ModuleSOName; ///< Module SOName (for shared format)
+ // @LOCALMOD-END
void *NamedMDSymTab; ///< NamedMDNode names.
friend class Constant;
@@ -234,6 +253,24 @@ public:
/// @returns a string containing the target triple.
const std::string &getTargetTriple() const { return TargetTriple; }
+ // @LOCALMOD-BEGIN
+
+ /// Get the module format
+ /// @returns the module format
+ OutputFormat getOutputFormat() const;
+
+ /// Get the SOName of this module.
+ /// @returns a string containing the module soname
+ const std::string &getSOName() const;
+
+ /// Record the needed information for a global value.
+ /// This creates a needed record for DynFile, if one does not already exist.
+ void addNeededRecord(StringRef DynFile, GlobalValue *GV);
+
+ // Fill NeededOut with all needed records present in the module.
+ void getNeededRecords(std::vector<NeededRecord> *NeededOut) const;
+ // @LOCALMOD-END
+
/// Get the target endian information.
/// @returns Endianess - an enumeration for the endianess of the target
Endianness getEndianness() const;
@@ -263,6 +300,18 @@ public:
/// Set the target triple.
void setTargetTriple(StringRef T) { TargetTriple = T; }
+ /// @LOCALMOD-BEGIN
+
+ /// Set the module format
+ void setOutputFormat(OutputFormat F);
+
+ /// For modules with output format "shared", set the output soname.
+ void setSOName(StringRef Name);
+
+ /// Wrap a global symbol.
+ void wrapSymbol(StringRef SymName);
+ /// @LOCALMOD-END
+
/// Set the module-scope inline assembly blocks.
void setModuleInlineAsm(StringRef Asm) {
GlobalScopeAsm = Asm;
@@ -584,6 +633,11 @@ public:
/// Dump the module to stderr (for debugging).
void dump() const;
+ /// @LOCALMOD-BEGIN
+ /// Print the PNaCl metadata for the module.
+ void dumpMeta(raw_ostream &OS) const;
+ /// @LOCALMOD-END
+
/// This function causes all the subinstructions to "let go" of all references
/// that they are maintaining. This allows one to 'delete' a whole class at
/// a time, even though there may be circular references... first all
diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h
index 13788832bd..dbd1091629 100644
--- a/include/llvm/Support/ELF.h
+++ b/include/llvm/Support/ELF.h
@@ -325,6 +325,7 @@ enum {
ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000
ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000
ELFOSABI_ARM = 97, // ARM
+ ELFOSABI_NACL = 123, // Native Client // @LOCALMOD
ELFOSABI_STANDALONE = 255 // Standalone (embedded) application
};
diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h
index dbcf0fd11d..5e98fbd07a 100644
--- a/include/llvm/Support/ValueHandle.h
+++ b/include/llvm/Support/ValueHandle.h
@@ -104,6 +104,11 @@ protected:
void setValPtrInt(unsigned K) { VP.setInt(K); }
unsigned getValPtrInt() const { return VP.getInt(); }
+ // @LOCALMOD-BEGIN -- Hack for bug:
+ // http://code.google.com/p/nativeclient/issues/detail?id=2786
+ void setKind(HandleBaseKind K) { PrevPair.setInt(K); }
+ // @LOCALMOD-END
+
static bool isValid(Value *V) {
return V &&
V != DenseMapInfo<Value *>::getEmptyKey() &&
@@ -232,6 +237,15 @@ public:
return getValPtr();
}
+ // @LOCALMOD-BEGIN -- Hack for bug:
+ // http://code.google.com/p/nativeclient/issues/detail?id=2786
+ // This allows us to weaken the Asserting Value Handle in LexicalScopes.h,
+ // for Debug info only.
+ void make_weak() {
+ setKind(Weak);
+ }
+ // @LOCALMOD-END
+
ValueTy *operator->() const { return getValPtr(); }
ValueTy &operator*() const { return *getValPtr(); }
};
diff --git a/include/llvm/Support/support_macros.h b/include/llvm/Support/support_macros.h
new file mode 100644
index 0000000000..83d62c722c
--- /dev/null
+++ b/include/llvm/Support/support_macros.h
@@ -0,0 +1,25 @@
+// Define support macros for defining classes, etc.
+
+#ifndef LLVM_SUPPORT_SUPPORT_MACROS_H__
+#define LLVM_SUPPORT_SUPPORT_MACROS_H__
+
+// Define macro, to use within a class declaration, to disallow constructor
+// copy. Defines copy constructor declaration under the assumption that it
+// is never defined.
+#define DISALLOW_CLASS_COPY(class_name) \
+ class_name(class_name& arg) // Do not implement
+
+// Define macro, to use within a class declaration, to disallow assignment.
+// Defines assignment operation declaration under the assumption that it
+// is never defined.
+#define DISALLOW_CLASS_ASSIGN(class_name) \
+ void operator=(class_name& arg) // Do not implement
+
+// Define macro to add copy and assignment declarations to a class file,
+// for which no bodies will be defined, effectively disallowing these from
+// being defined in the class.
+#define DISALLOW_CLASS_COPY_AND_ASSIGN(class_name) \
+ DISALLOW_CLASS_COPY(class_name); \
+ DISALLOW_CLASS_ASSIGN(class_name)
+
+#endif // LLVM_SUPPORT_SUPPORT_MACROS_H__
diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h
index 0d164f688d..844013ed5d 100644
--- a/include/llvm/Support/system_error.h
+++ b/include/llvm/Support/system_error.h
@@ -597,7 +597,7 @@ enum _ {
#else
stream_timeout = ETIMEDOUT,
#endif
- text_file_busy = ETXTBSY,
+ text_file_busy = EINVAL, // @LOCALMOD
timed_out = ETIMEDOUT,
too_many_files_open_in_system = ENFILE,
too_many_files_open = EMFILE,
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index a68eb8339d..ed3db69a4e 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -766,6 +766,40 @@ def LIFETIME_END : Instruction {
let AsmString = "LIFETIME_END";
let neverHasSideEffects = 1;
}
+// @LOCALMOD-BEGIN
+def BUNDLE_ALIGN_START : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins);
+ let AsmString = "";
+ let neverHasSideEffects = 1;
+ let isAsCheapAsAMove = 1;
+ let isNotDuplicable = 1;
+}
+def BUNDLE_ALIGN_END : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins);
+ let AsmString = "";
+ let neverHasSideEffects = 1;
+ let isAsCheapAsAMove = 1;
+ let isNotDuplicable = 1;
+}
+def BUNDLE_LOCK : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins);
+ let AsmString = "";
+ let neverHasSideEffects = 1;
+ let isAsCheapAsAMove = 1;
+ let isNotDuplicable = 1;
+}
+def BUNDLE_UNLOCK : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins);
+ let AsmString = "";
+ let neverHasSideEffects = 1;
+ let isAsCheapAsAMove = 1;
+ let isNotDuplicable = 1;
+}
+// @LOCALMOD-END
}
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h
index d56db7b511..7df3bfa473 100644
--- a/include/llvm/Target/TargetFrameLowering.h
+++ b/include/llvm/Target/TargetFrameLowering.h
@@ -48,11 +48,19 @@ private:
unsigned StackAlignment;
unsigned TransientStackAlignment;
int LocalAreaOffset;
+
+ // @LOCALMOD-BEGIN
+ // TODO(pdox): Refactor this and upstream it, to get rid of the
+ // assumption that StackSlotSize == PointerSize.
+ unsigned StackSlotSize;
+ // @LOCALMOD-END
public:
- TargetFrameLowering(StackDirection D, unsigned StackAl, int LAO,
- unsigned TransAl = 1)
+ TargetFrameLowering(StackDirection D,
+ unsigned StackAl, int LAO,
+ unsigned TransAl = 1,
+ unsigned SlotSize = 0) // @LOCALMOD
: StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl),
- LocalAreaOffset(LAO) {}
+ LocalAreaOffset(LAO), StackSlotSize(SlotSize) {}
virtual ~TargetFrameLowering();
@@ -63,6 +71,11 @@ public:
///
StackDirection getStackGrowthDirection() const { return StackDir; }
+ // @LOCALMOD-BEGIN
+ /// getStackSlotSize - Return the size of a stack slot
+ unsigned getStackSlotSize() const { return StackSlotSize; }
+ // @LOCALMOD-END
+
/// getStackAlignment - This method returns the number of bytes to which the
/// stack pointer must be aligned on entry to a function. Typically, this
/// is the largest alignment for any data object in the target.
diff --git a/include/llvm/Target/TargetJITInfo.h b/include/llvm/Target/TargetJITInfo.h
index 044afd9b73..c2bb376131 100644
--- a/include/llvm/Target/TargetJITInfo.h
+++ b/include/llvm/Target/TargetJITInfo.h
@@ -129,6 +129,25 @@ namespace llvm {
/// separately allocated heap memory rather than in the same
/// code memory allocated by JITCodeEmitter.
virtual bool allocateSeparateGVMemory() const { return false; }
+
+ // @LOCALMOD-START
+ // NaCl-specific, target-specific stuff
+ typedef struct { uint8_t *ins; int len; } HaltInstruction;
+ /// Get a sequence of NOPs of length len. Returns a pointer to a buffer
+ /// containing a val
+ virtual const uint8_t *getNopSequence(size_t len) const { return NULL; }
+ /// Get the length and definition of the halt/roadblock instruction
+ virtual const HaltInstruction *getHalt() const { return NULL; }
+ virtual int getBundleSize() const { return 0; }
+ virtual int32_t getJumpMask() const { return 0; }
+
+ /// Relocations cannot happen in-place in NaCl because we can't write to
+ /// code. This function takes a pointer to where the code has been emitted,
+ /// before it is copied to the code region. The subsequent call to
+ /// relocate takes pointers to the target code location, but rewrites the
+ /// code in the relocation buffer rather than at the target
+ virtual void setRelocationBuffer(unsigned char * BufferBegin) {}
+ // @LOCALMOD-END
protected:
bool useGOT;
};
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 9e46a40e29..a78ef58b88 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -116,6 +116,18 @@ public:
// mask (ex: x86 blends).
};
+ // @LOCALMOD-START
+ // This needs to be kept in sync with
+ // native_client/src/untrusted/nacl/pnaclintrin.h.
+ enum PnaclTargetArchitecture {
+ PnaclTargetArchitectureInvalid = 0,
+ PnaclTargetArchitectureX86_32,
+ PnaclTargetArchitectureX86_64,
+ PnaclTargetArchitectureARM_32,
+ PnaclTargetArchitectureARM_32_Thumb
+ };
+ // @LOCALMOD-END
+
static ISD::NodeType getExtendForContent(BooleanContent Content) {
switch (Content) {
case UndefinedBooleanContent:
diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h
index 516e0706b8..2c9459974a 100644
--- a/include/llvm/Target/TargetOpcodes.h
+++ b/include/llvm/Target/TargetOpcodes.h
@@ -91,7 +91,14 @@ namespace TargetOpcode {
/// Lifetime markers.
LIFETIME_START = 15,
- LIFETIME_END = 16
+ LIFETIME_END = 16,
+
+ // @LOCALMOD-BEGIN
+ BUNDLE_ALIGN_START = 14,
+ BUNDLE_ALIGN_END = 15,
+ BUNDLE_LOCK = 16,
+ BUNDLE_UNLOCK = 17
+ // @LOCALMOD-END
};
} // end namespace TargetOpcode
} // end namespace llvm
diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h
index 68ca567836..0a1b73e352 100644
--- a/include/llvm/Target/TargetOptions.h
+++ b/include/llvm/Target/TargetOptions.h
@@ -30,6 +30,12 @@ namespace llvm {
};
}
+ // @LOCALMOD-BEGIN
+ /// TLSUseCall - This flag enables the use of a function call to get the
+ /// thread pointer for TLS accesses, instead of using inline code.
+ extern bool TLSUseCall;
+ // @LOCALMOD-END
+
namespace FPOpFusion {
enum FPOpFusionMode {
Fast, // Enable fusion of FP ops wherever it's profitable.
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index a5d8eed746..1ddca844c9 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -372,7 +372,7 @@ extern char &InstructionSimplifierID;
// "block_weights" metadata.
FunctionPass *createLowerExpectIntrinsicPass();
-
+FunctionPass *createNaClCcRewritePass(const TargetLowering *TLI = 0);
} // End llvm namespace
#endif
diff --git a/include/llvm/Value.h b/include/llvm/Value.h
index 6560a420bf..41acc84415 100644
--- a/include/llvm/Value.h
+++ b/include/llvm/Value.h
@@ -105,6 +105,12 @@ public:
///
Type *getType() const { return VTy; }
+ // @LOCALMOD-START
+ // Currently only used for function type update during
+ // the NaCl calling convention rewrite pass
+ void setType(Type* t) { VTy = t; }
+ // @LOCALMOD-END
+
/// All values hold a context through their type.
LLVMContext &getContext() const;
diff --git a/include/llvm/Wrap/BCHeaderField.h b/include/llvm/Wrap/BCHeaderField.h
new file mode 100644
index 0000000000..40a3714c9f
--- /dev/null
+++ b/include/llvm/Wrap/BCHeaderField.h
@@ -0,0 +1,106 @@
+/* Copyright 2012 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ */
+
+#ifndef LLVM_WRAP_BCHEADERFIELD_H
+#define LLVM_WRAP_BCHEADERFIELD_H
+#include <limits>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+// Class representing a variable-size metadata field in the bitcode header.
+// Also contains the list of known Tag IDs.
+// Contains a pointer to the data but does not own the data, so it can be
+// copied with the trivial copy constructor/assignment operator.
+
+// The serialized format has 2 fixed subfields (ID and length) and the
+// variable-length data subfield
+class BCHeaderField {
+ public:
+ typedef enum {
+ kInvalid = 0,
+ kBitcodeHash = 1,
+ kAndroidCompilerVersion = 0x4001,
+ kAndroidOptimizationLevel = 0x4002
+ } Tag;
+ typedef uint16_t FixedSubfield;
+
+ BCHeaderField(Tag ID, size_t len, uint8_t* data) :
+ ID_(ID), len_(len), data_(data) {}
+ size_t GetTotalSize() {
+ // Round up to 4 byte alignment
+ return (kTagLenSize + len_ + 3) & ~3;
+ }
+
+ bool Write(uint8_t* buf, size_t buf_len) {
+ size_t fields_len = kTagLenSize + len_;
+ size_t pad_len = (4 - (fields_len & 3)) & 3;
+ // Ensure buffer is large enough and that length can be represented
+ // in 16 bits
+ if (buf_len < fields_len + pad_len ||
+ len_ > std::numeric_limits<FixedSubfield>::max()) return false;
+
+ WriteFixedSubfield(static_cast<FixedSubfield>(ID_), buf);
+ WriteFixedSubfield(static_cast<FixedSubfield>(len_),
+ buf + sizeof(FixedSubfield));
+ memcpy(buf + kTagLenSize, data_, len_);
+ // Pad out to 4 byte alignment
+ if (pad_len) {
+ memset(buf + fields_len, 0, pad_len);
+ }
+ return true;
+ }
+
+ bool Read(const uint8_t* buf, size_t buf_len) {
+ if (buf_len < kTagLenSize) return false;
+ FixedSubfield field;
+ ReadFixedSubfield(&field, buf);
+ ID_ = static_cast<Tag>(field);
+ ReadFixedSubfield(&field, buf + sizeof(FixedSubfield));
+ len_ = static_cast<size_t>(field);
+ if (buf_len < kTagLenSize + len_) return false;
+ memcpy(data_, buf + kTagLenSize, len_);
+ return true;
+ }
+
+ void Print() {
+ fprintf(stderr, "Field ID: %d, data length %d, total length %d\n",
+ ID_, static_cast<int>(len_), static_cast<int>(GetTotalSize()));
+ fprintf(stderr, "Data: ");
+ for (size_t i = 0; i < len_; i++) fprintf(stderr, "%02x", data_[i]);
+ fprintf(stderr, "\n");
+ }
+
+ // Get the data size from a serialized field to allow allocation
+ static size_t GetDataSizeFromSerialized(const uint8_t* buf) {
+ FixedSubfield len;
+ ReadFixedSubfield(&len, buf + sizeof(FixedSubfield));
+ return len;
+ }
+
+ Tag getID() const {
+ return ID_;
+ }
+
+ size_t getLen() const {
+ return len_;
+ }
+
+ private:
+ // Combined size of the fixed subfields
+ const static size_t kTagLenSize = 2 * sizeof(FixedSubfield);
+ static void WriteFixedSubfield(FixedSubfield value, uint8_t* buf) {
+ buf[0] = value & 0xFF;
+ buf[1] = (value >> 8) & 0xFF;
+ }
+ static void ReadFixedSubfield(FixedSubfield* value, const uint8_t* buf) {
+ *value = buf[0] | buf[1] << 8;
+ }
+ Tag ID_;
+ size_t len_;
+ uint8_t *data_;
+};
+
+#endif
diff --git a/include/llvm/Wrap/bitcode_wrapperer.h b/include/llvm/Wrap/bitcode_wrapperer.h
new file mode 100644
index 0000000000..89f2a4cbcc
--- /dev/null
+++ b/include/llvm/Wrap/bitcode_wrapperer.h
@@ -0,0 +1,192 @@
+/* Copyright 2012 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ */
+
+// Define utility class to wrap/unwrap bitcode files. Does wrapping/unwrapping
+// in such a way that the wrappered bitcode file is still a bitcode file.
+
+#ifndef LLVM_WRAP_BITCODE_WRAPPERER_H__
+#define LLVM_WRAP_BITCODE_WRAPPERER_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include <vector>
+
+#include "llvm/Support/support_macros.h"
+#include "llvm/Wrap/BCHeaderField.h"
+#include "llvm/Wrap/wrapper_input.h"
+#include "llvm/Wrap/wrapper_output.h"
+
+// The bitcode wrapper header is the following 7 fixed 4-byte fields:
+// 1) 0B17C0DE - The magic number expected by llvm for wrapped bitcodes
+// 2) Version # 0 - The current version of wrapped bitcode files
+// 3) (raw) bitcode offset
+// 4) (raw) bitcode size
+// 5) Android header version
+// 6) Android target API
+// 7) PNaCl Bitcode version
+// plus 0 or more variable-length fields (consisting of ID, length, data)
+
+// Initial buffer size. It is expanded if needed to hold large variable-size
+// fields.
+static const size_t kBitcodeWrappererBufferSize = 1024;
+
+// Support class for outputting a wrapped bitcode file from a raw bitcode
+// file (and optionally additional header fields), or for outputting a raw
+// bitcode file from a wrapped one.
+class BitcodeWrapperer {
+ public:
+ // Create a bitcode wrapperer using the following
+ // input and output files.
+ BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile);
+
+ // Returns true if the input file begins with a bitcode
+ // wrapper magic number. As a side effect, _wrapper_ fields are set.
+ bool IsInputBitcodeWrapper();
+
+ // Returns true if the input file begins with a bitcode
+ // file magic number.
+ bool IsInputBitcodeFile();
+
+ // Add a variable-length field to the header. The caller is responsible
+ // for freeing the data pointed to by the BCHeaderField.
+ void AddHeaderField(BCHeaderField* field);
+
+ // Generate a wrapped bitcode file from the input bitcode file
+ // and the current header data. Return true on success.
+ bool GenerateWrappedBitcodeFile();
+
+ // Unwrap the wrapped bitcode file, to the corresponding
+ // outfile. Return true on success.
+ bool GenerateRawBitcodeFile();
+
+ // Print current wrapper header fields to stderr for debugging.
+ void PrintWrapperHeader();
+
+ ~BitcodeWrapperer();
+
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(BitcodeWrapperer);
+
+ // Refills the buffer with more bytes. Does this in a way
+ // such that it is maximally filled.
+ void FillBuffer();
+
+ // Returns the number of bytes in infile.
+ off_t GetInFileSize() {
+ if (infile_ != NULL) {
+ return infile_->Size();
+ } else {
+ return 0;
+ }
+ }
+
+ // Returns the offset of bitcode (i.e. the size of the wrapper header)
+ // if the output file were to be written now.
+ size_t BitcodeOffset();
+
+ // Returns true if we can read a word. If necessary, fills the buffer
+ // with enough characters so that there are at least a 32-bit value
+ // in the buffer. Returns false if there isn't a 32-bit value
+ // to read from the input file.
+ bool CanReadWord();
+
+ // Read a (32-bit) word from the input. Return true
+ // if able to read the word.
+ bool ReadWord(uint32_t& word);
+
+ // Write a (32-bit) word to the output. Return true if successful
+ bool WriteWord(uint32_t word);
+
+ // Write all variable-sized header fields to the output. Return true
+ // if successful.
+ bool WriteVariableFields();
+
+ // Parse the bitcode wrapper header in the infile, if any. Return true
+ // if successful.
+ bool ParseWrapperHeader();
+
+ // Returns the i-th character in front of the cursor in the buffer.
+ uint8_t BufferLookahead(int i) { return buffer_[cursor_ + i]; }
+
+ // Returns how many unread bytes are in the buffer.
+ size_t GetBufferUnreadBytes() { return buffer_size_ - cursor_; }
+
+
+ // Backs up the read cursor to the beginning of the input buffer.
+ void ResetCursor() {
+ cursor_ = 0;
+ }
+
+ // Generates the header sequence for the wrapped bitcode being
+ // generated.
+ bool WriteBitcodeWrapperHeader();
+
+ // Copies size bytes of infile to outfile, using the buffer.
+ bool BufferCopyInToOut(uint32_t size);
+
+ // Discards the old infile and replaces it with the given file.
+ void ReplaceInFile(WrapperInput* new_infile);
+
+ // Discards the old outfile and replaces it with the given file.
+ void ReplaceOutFile(WrapperOutput* new_outfile);
+
+ // Moves to the given position in the input file. Returns false
+ // if unsuccessful.
+ bool Seek(uint32_t pos);
+
+ // Clear the buffer of all contents.
+ void ClearBuffer();
+
+ // The input file being processed. Can be either
+ // a bitcode file, a wrappered bitcode file, or a secondary
+ // file to be wrapped.
+ WrapperInput* infile_;
+
+ // The output file being generated. Can be either
+ // a bitcode file, a wrappered bitcode file, or a secondary
+ // unwrapped file.
+ WrapperOutput* outfile_;
+
+ // A buffer of bytes read from the input file.
+ std::vector<uint8_t> buffer_;
+
+ // The number of bytes that were read from the input file
+ // into the buffer.
+ size_t buffer_size_;
+
+ // The index to the current read point within the buffer.
+ size_t cursor_;
+
+ // True when eof of input is reached.
+ bool infile_at_eof_;
+
+ // The 32-bit value defining the offset of the raw bitcode in the input file.
+ uint32_t infile_bc_offset_;
+
+ // The 32-bit value defining the generated offset of the wrapped bitcode.
+ // This value changes as new fields are added with AddHeaderField
+ uint32_t wrapper_bc_offset_;
+
+ // The 32-bit value defining the size of the raw wrapped bitcode.
+ uint32_t wrapper_bc_size_;
+
+ // Android header version and target API
+ uint32_t android_header_version_;
+ uint32_t android_target_api_;
+
+ // PNaCl bitcode version
+ uint32_t pnacl_bc_version_;
+
+ // Vector of variable header fields
+ std::vector<BCHeaderField> header_fields_;
+ // If any bufferdata from header fields is owned, it is stored here and
+ // freed on destruction.
+ std::vector<uint8_t*> variable_field_data_;
+
+ // True if there was an error condition (e.g. the file is not bitcode)
+ bool error_;
+};
+
+#endif // LLVM_WRAP_BITCODE_WRAPPERER_H__
diff --git a/include/llvm/Wrap/file_wrapper_input.h b/include/llvm/Wrap/file_wrapper_input.h
new file mode 100644
index 0000000000..9f3de004c4
--- /dev/null
+++ b/include/llvm/Wrap/file_wrapper_input.h
@@ -0,0 +1,48 @@
+/* Copyright 2012 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ */
+
+// Defines utility allowing files for bitcode input wrapping.
+
+#ifndef FILE_WRAPPER_INPUT_H__
+#define FILE_WRAPPER_INPUT_H__
+
+#include "llvm/Support/support_macros.h"
+#include "llvm/Wrap/wrapper_input.h"
+
+#include <stdio.h>
+#include <string>
+
+// Define a class to wrap named files.
+class FileWrapperInput : public WrapperInput {
+ public:
+ FileWrapperInput(const std::string& name);
+ ~FileWrapperInput();
+ // Tries to read the requested number of bytes into the buffer. Returns the
+ // actual number of bytes read.
+ virtual size_t Read(uint8_t* buffer, size_t wanted);
+ // Returns true if at end of file. Note: May return false
+ // until Read is called, and returns 0.
+ virtual bool AtEof();
+ // Returns the size of the file (in bytes).
+ virtual off_t Size();
+ // Moves to the given offset within the file. Returns
+ // false if unable to move to that position.
+ virtual bool Seek(uint32_t pos);
+ private:
+ // The name of the file.
+ std::string _name;
+ // True once eof has been encountered.
+ bool _at_eof;
+ // True if size has been computed.
+ bool _size_found;
+ // The size of the file.
+ off_t _size;
+ // The corresponding (opened) file.
+ FILE* _file;
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(FileWrapperInput);
+};
+
+#endif // FILE_WRAPPER_INPUT_H__
diff --git a/include/llvm/Wrap/file_wrapper_output.h b/include/llvm/Wrap/file_wrapper_output.h
new file mode 100644
index 0000000000..714bd36a75
--- /dev/null
+++ b/include/llvm/Wrap/file_wrapper_output.h
@@ -0,0 +1,34 @@
+/* Copyright 2012 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ */
+
+// Defines utility allowing files for bitcode output wrapping.
+
+#ifndef FILE_WRAPPER_OUTPUT_H__
+#define FILE_WRAPPER_OUTPUT_H__
+
+#include "llvm/Support/support_macros.h"
+#include "llvm/Wrap/wrapper_output.h"
+#include <stdio.h>
+#include <string>
+
+// Define a class to wrap named files. */
+class FileWrapperOutput : public WrapperOutput {
+ public:
+ FileWrapperOutput(const std::string& name);
+ ~FileWrapperOutput();
+ // Writes a single byte, returning false if unable to write.
+ virtual bool Write(uint8_t byte);
+ // Writes the specified number of bytes in the buffer to
+ // output. Returns false if unable to write.
+ virtual bool Write(const uint8_t* buffer, size_t buffer_size);
+ private:
+ // The name of the file
+ std::string _name;
+ // The corresponding (opened) file.
+ FILE* _file;
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(FileWrapperOutput);
+};
+#endif // FILE_WRAPPER_OUTPUT_H__
diff --git a/include/llvm/Wrap/wrapper_input.h b/include/llvm/Wrap/wrapper_input.h
new file mode 100644
index 0000000000..cde918083a
--- /dev/null
+++ b/include/llvm/Wrap/wrapper_input.h
@@ -0,0 +1,38 @@
+/* Copyright 2012 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ */
+
+// Define a generic interface to a file/memory region that contains
+// a bitcode file, a wrapped bitcode file, or a data file to wrap.
+
+#ifndef LLVM_WRAP_WRAPPER_INPUT_H__
+#define LLVM_WRAP_WRAPPER_INPUT_H__
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "llvm/Support/support_macros.h"
+
+// The following is a generic interface to a file/memory region that contains
+// a bitcode file, a wrapped bitcode file, or data file to wrap.
+class WrapperInput {
+ public:
+ WrapperInput() {}
+ virtual ~WrapperInput() {}
+ // Tries to read the requested number of bytes into the buffer. Returns the
+ // actual number of bytes read.
+ virtual size_t Read(uint8_t* buffer, size_t wanted) = 0;
+ // Returns true if at end of input. Note: May return false until
+ // Read is called, and returns 0.
+ virtual bool AtEof() = 0;
+ // Returns the size of the input (in bytes).
+ virtual off_t Size() = 0;
+ // Moves to the given offset within the input region. Returns false
+ // if unable to move to that position.
+ virtual bool Seek(uint32_t pos) = 0;
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(WrapperInput);
+};
+
+#endif // LLVM_WRAP_WRAPPER_INPUT_H__
diff --git a/include/llvm/Wrap/wrapper_output.h b/include/llvm/Wrap/wrapper_output.h
new file mode 100644
index 0000000000..7045705991
--- /dev/null
+++ b/include/llvm/Wrap/wrapper_output.h
@@ -0,0 +1,34 @@
+/* Copyright 2012 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ */
+
+// Defines a generic interface to a file/memory region that
+// contains a generated wrapped bitcode file, bitcode file,
+// or data file.
+
+#ifndef LLVM_WRAP_WRAPPER_OUTPUT_H__
+#define LLVM_WRAP_WRAPPER_OUTPUT_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "llvm/Support/support_macros.h"
+
+// The following is a generic interface to a file/memory region
+// that contains a generated bitcode file, wrapped bitcode file,
+// or a data file.
+class WrapperOutput {
+ public:
+ WrapperOutput() {}
+ virtual ~WrapperOutput() {}
+ // Writes a single byte, returning false if unable to write.
+ virtual bool Write(uint8_t byte) = 0;
+ // Writes the specified number of bytes in the buffer to
+ // output. Returns false if unable to write.
+ virtual bool Write(const uint8_t* buffer, size_t buffer_size);
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(WrapperOutput);
+};
+
+#endif // LLVM_WRAP_WRAPPER_OUTPUT_H__