diff options
author | Stephen Hines <srhines@google.com> | 2014-02-11 20:01:10 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-02-11 20:01:10 -0800 |
commit | ce9904c6ea8fd669978a8eefb854b330eb9828ff (patch) | |
tree | 2418ee2e96ea220977c8fb74959192036ab5b133 /include | |
parent | c27b10b198c1d9e9b51f2303994313ec2778edd7 (diff) | |
parent | dbb832b83351cec97b025b61c26536ef50c3181c (diff) | |
download | external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.zip external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.gz external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.bz2 |
Merge remote-tracking branch 'upstream/release_34' into merge-20140211
Conflicts:
lib/Linker/LinkModules.cpp
lib/Support/Unix/Signals.inc
Change-Id: Ia54f291fa5dc828052d2412736e8495c1282aa64
Diffstat (limited to 'include')
251 files changed, 13390 insertions, 10225 deletions
diff --git a/include/llvm-c/BitReader.h b/include/llvm-c/BitReader.h index 5228035..7af209b 100644 --- a/include/llvm-c/BitReader.h +++ b/include/llvm-c/BitReader.h @@ -34,7 +34,7 @@ extern "C" { /* Builds a module from the bitcode in the specified memory buffer, returning a reference to the module via the OutModule parameter. Returns 0 on success. - Optionally returns a human-readable error message via OutMessage. */ + Optionally returns a human-readable error message via OutMessage. */ LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule, char **OutMessage); @@ -44,7 +44,7 @@ LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, /** Reads a module from the specified path, returning via the OutMP parameter a module provider which performs lazy deserialization. Returns 0 on success. - Optionally returns a human-readable error message via OutMessage. */ + Optionally returns a human-readable error message via OutMessage. */ LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, diff --git a/include/llvm-c/BitWriter.h b/include/llvm-c/BitWriter.h index ba5a677..f605e24 100644 --- a/include/llvm-c/BitWriter.h +++ b/include/llvm-c/BitWriter.h @@ -34,7 +34,7 @@ extern "C" { /*===-- Operations on modules ---------------------------------------------===*/ -/** Writes a module to the specified path. Returns 0 on success. */ +/** Writes a module to the specified path. Returns 0 on success. */ int LLVMWriteBitcodeToFile(LLVMModuleRef M, const char *Path); /** Writes a module to an open file descriptor. Returns 0 on success. */ @@ -42,7 +42,7 @@ int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose, int Unbuffered); /** Deprecated for LLVMWriteBitcodeToFD. Writes a module to an open file - descriptor. Returns 0 on success. Closes the Handle. */ + descriptor. Returns 0 on success. Closes the Handle. */ int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle); /** diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 409c0f1..9953d52 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -165,8 +165,9 @@ typedef enum { a temporary measure until the API/ABI impact to the C API is understood and the path forward agreed upon. LLVMAddressSafety = 1ULL << 32, - LLVMStackProtectStrongAttribute = 1ULL<<33 - LLVMCold = 1ULL << 34 + LLVMStackProtectStrongAttribute = 1ULL<<33, + LLVMCold = 1ULL << 34, + LLVMOptimizeNone = 1ULL << 35 */ } LLVMAttribute; @@ -221,6 +222,7 @@ typedef enum { LLVMPtrToInt = 39, LLVMIntToPtr = 40, LLVMBitCast = 41, + LLVMAddrSpaceCast = 60, /* Other Operators */ LLVMICmp = 42, @@ -273,7 +275,7 @@ typedef enum { LLVMLinkOnceAnyLinkage, /**< Keep one copy of function when linking (inline)*/ LLVMLinkOnceODRLinkage, /**< Same, but only replaced by something equivalent. */ - LLVMLinkOnceODRAutoHideLinkage, /**< Like LinkOnceODR, but possibly hidden. */ + LLVMLinkOnceODRAutoHideLinkage, /**< Obsolete */ LLVMWeakAnyLinkage, /**< Keep one copy of function when linking (weak) */ LLVMWeakODRLinkage, /**< Same, but only replaced by something equivalent. */ @@ -300,6 +302,8 @@ typedef enum { LLVMCCallConv = 0, LLVMFastCallConv = 8, LLVMColdCallConv = 9, + LLVMWebKitJSCallConv = 12, + LLVMAnyRegCallConv = 13, LLVMX86StdcallCallConv = 64, LLVMX86FastcallCallConv = 65 } LLVMCallConv; @@ -353,26 +357,26 @@ typedef enum { LLVMAtomicOrderingNotAtomic = 0, /**< A load or store which is not atomic */ LLVMAtomicOrderingUnordered = 1, /**< Lowest level of atomicity, guarantees somewhat sane results, lock free. */ - LLVMAtomicOrderingMonotonic = 2, /**< guarantees that if you take all the - operations affecting a specific address, + LLVMAtomicOrderingMonotonic = 2, /**< guarantees that if you take all the + operations affecting a specific address, a consistent ordering exists */ - LLVMAtomicOrderingAcquire = 4, /**< Acquire provides a barrier of the sort - necessary to acquire a lock to access other + LLVMAtomicOrderingAcquire = 4, /**< Acquire provides a barrier of the sort + necessary to acquire a lock to access other memory with normal loads and stores. */ - LLVMAtomicOrderingRelease = 5, /**< Release is similar to Acquire, but with - a barrier of the sort necessary to release + LLVMAtomicOrderingRelease = 5, /**< Release is similar to Acquire, but with + a barrier of the sort necessary to release a lock. */ - LLVMAtomicOrderingAcquireRelease = 6, /**< provides both an Acquire and a - Release barrier (for fences and + LLVMAtomicOrderingAcquireRelease = 6, /**< provides both an Acquire and a + Release barrier (for fences and operations which both read and write memory). */ - LLVMAtomicOrderingSequentiallyConsistent = 7 /**< provides Acquire semantics - for loads and Release - semantics for stores. - Additionally, it guarantees - that a total ordering exists - between all - SequentiallyConsistent + LLVMAtomicOrderingSequentiallyConsistent = 7 /**< provides Acquire semantics + for loads and Release + semantics for stores. + Additionally, it guarantees + that a total ordering exists + between all + SequentiallyConsistent operations. */ } LLVMAtomicOrdering; @@ -385,16 +389,16 @@ typedef enum { LLVMAtomicRMWBinOpOr, /**< OR a value and return the old one */ LLVMAtomicRMWBinOpXor, /**< Xor a value and return the old one */ LLVMAtomicRMWBinOpMax, /**< Sets the value if it's greater than the - original using a signed comparison and return + original using a signed comparison and return the old one */ LLVMAtomicRMWBinOpMin, /**< Sets the value if it's Smaller than the - original using a signed comparison and return + original using a signed comparison and return the old one */ LLVMAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the - original using an unsigned comparison and return + original using an unsigned comparison and return the old one */ LLVMAtomicRMWBinOpUMin /**< Sets the value if it's greater than the - original using an unsigned comparison and return + original using an unsigned comparison and return the old one */ } LLVMAtomicRMWBinOp; @@ -407,7 +411,7 @@ void LLVMInitializeCore(LLVMPassRegistryRef R); /** Deallocate and destroy all ManagedStatic variables. @see llvm::llvm_shutdown @see ManagedStatic */ -void LLVMShutdown(); +void LLVMShutdown(void); /*===-- Error handling ----------------------------------------------------===*/ @@ -415,6 +419,29 @@ void LLVMShutdown(); char *LLVMCreateMessage(const char *Message); void LLVMDisposeMessage(char *Message); +typedef void (*LLVMFatalErrorHandler)(const char *Reason); + +/** + * Install a fatal error handler. By default, if LLVM detects a fatal error, it + * will call exit(1). This may not be appropriate in many contexts. For example, + * doing exit(1) will bypass many crash reporting/tracing system tools. This + * function allows you to install a callback that will be invoked prior to the + * call to exit(1). + */ +void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler); + +/** + * Reset the fatal error handler. This resets LLVM's fatal error handling + * behavior to the default. + */ +void LLVMResetFatalErrorHandler(void); + +/** + * Enable LLVM's built-in stack trace code. This intercepts the OS's crash + * signals and prints which component of LLVM you were in at the time if the + * crash. + */ +void LLVMEnablePrettyStackTrace(void); /** * @defgroup LLVMCCoreContext Contexts @@ -460,7 +487,7 @@ unsigned LLVMGetMDKindID(const char* Name, unsigned SLen); /** * @defgroup LLVMCCoreModule Modules * - * Modules represent the top-level structure in a LLVM program. An LLVM + * Modules represent the top-level structure in an LLVM program. An LLVM * module is effectively a translation unit or a collection of * translation units merged together. * @@ -540,6 +567,14 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, char **ErrorMessage); /** + * Return a string representation of the module. Use + * LLVMDisposeMessage to free the string. + * + * @see Module::print() + */ +char *LLVMPrintModuleToString(LLVMModuleRef M); + +/** * Set inline assembly for a module. * * @see Module::setModuleInlineAsm() @@ -691,6 +726,21 @@ LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty); LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty); /** + * Dump a representation of a type to stderr. + * + * @see llvm::Type::dump() + */ +void LLVMDumpType(LLVMTypeRef Val); + +/** + * Return a string representation of the type. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::Type::print() + */ +char *LLVMPrintTypeToString(LLVMTypeRef Val); + +/** * @defgroup LLVMCCoreTypeInt Integer Types * * Functions in this section operate on integer types. @@ -1041,7 +1091,7 @@ LLVMTypeRef LLVMX86MMXType(void); * hierarchy of classes within this type. Depending on the instance * obtained, not all APIs are available. * - * Callers can determine the type of a LLVMValueRef by calling the + * Callers can determine the type of an LLVMValueRef by calling the * LLVMIsA* family of functions (e.g. LLVMIsAArgument()). These * functions are defined by a macro, so it isn't obvious which are * available by looking at the Doxygen source code. Instead, look at the @@ -1063,6 +1113,9 @@ LLVMTypeRef LLVMX86MMXType(void); macro(BlockAddress) \ macro(ConstantAggregateZero) \ macro(ConstantArray) \ + macro(ConstantDataSequential) \ + macro(ConstantDataArray) \ + macro(ConstantDataVector) \ macro(ConstantExpr) \ macro(ConstantFP) \ macro(ConstantInt) \ @@ -1107,6 +1160,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(UnaryInstruction) \ macro(AllocaInst) \ macro(CastInst) \ + macro(AddrSpaceCastInst) \ macro(BitCastInst) \ macro(FPExtInst) \ macro(FPToSIInst) \ @@ -1162,6 +1216,14 @@ void LLVMSetValueName(LLVMValueRef Val, const char *Name); void LLVMDumpValue(LLVMValueRef Val); /** + * Return a string representation of the value. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::Value::print() + */ +char *LLVMPrintValueToString(LLVMValueRef Val); + +/** * Replace all uses of a value with another one. * * @see llvm::Value::replaceAllUsesWith() @@ -1181,7 +1243,7 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val); /** * Convert value instances between types. * - * Internally, a LLVMValueRef is "pinned" to a specific type. This + * Internally, an LLVMValueRef is "pinned" to a specific type. This * series of functions allows you to cast an instance to a specific * type. * @@ -1203,7 +1265,7 @@ LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) * This module defines functions that allow you to inspect the uses of a * LLVMValueRef. * - * It is possible to obtain a LLVMUseRef for any LLVMValueRef instance. + * It is possible to obtain an LLVMUseRef for any LLVMValueRef instance. * Each LLVMUseRef (which corresponds to a llvm::Use instance) holds a * llvm::User and llvm::Value. * @@ -1570,6 +1632,7 @@ LLVMValueRef LLVMConstFPToSI(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstPtrToInt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstIntToPtr(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstAddrSpaceCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstZExtOrBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstSExtOrBitCast(LLVMValueRef ConstantVal, @@ -1625,8 +1688,33 @@ const char *LLVMGetSection(LLVMValueRef Global); void LLVMSetSection(LLVMValueRef Global, const char *Section); LLVMVisibility LLVMGetVisibility(LLVMValueRef Global); void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz); -unsigned LLVMGetAlignment(LLVMValueRef Global); -void LLVMSetAlignment(LLVMValueRef Global, unsigned Bytes); + +/** + * @defgroup LLVMCCoreValueWithAlignment Values with alignment + * + * Functions in this group only apply to values with alignment, i.e. + * global variables, load and store instructions. + */ + +/** + * Obtain the preferred alignment of the value. + * @see llvm::LoadInst::getAlignment() + * @see llvm::StoreInst::getAlignment() + * @see llvm::GlobalValue::getAlignment() + */ +unsigned LLVMGetAlignment(LLVMValueRef V); + +/** + * Set the preferred alignment of the value. + * @see llvm::LoadInst::setAlignment() + * @see llvm::StoreInst::setAlignment() + * @see llvm::GlobalValue::setAlignment() + */ +void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes); + +/** + * @} + */ /** * @defgroup LLVMCoreValueConstantGlobalVariable Global Variables @@ -1806,7 +1894,7 @@ LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index); /** * Obtain the function to which this argument belongs. * - * Unlike other functions in this group, this one takes a LLVMValueRef + * Unlike other functions in this group, this one takes an LLVMValueRef * that corresponds to a llvm::Attribute. * * The returned LLVMValueRef is the llvm::Function to which this @@ -1831,7 +1919,7 @@ LLVMValueRef LLVMGetLastParam(LLVMValueRef Fn); /** * Obtain the next parameter to a function. * - * This takes a LLVMValueRef obtained from LLVMGetFirstParam() (which is + * This takes an LLVMValueRef obtained from LLVMGetFirstParam() (which is * actually a wrapped iterator) and obtains the next parameter from the * underlying iterator. */ @@ -1980,12 +2068,12 @@ void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest); LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB); /** - * Determine whether a LLVMValueRef is itself a basic block. + * Determine whether an LLVMValueRef is itself a basic block. */ LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val); /** - * Convert a LLVMValueRef to a LLVMBasicBlockRef instance. + * Convert an LLVMValueRef to an LLVMBasicBlockRef instance. */ LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val); @@ -2142,7 +2230,7 @@ LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB); /** * Obtain the last instruction in a basic block. * - * The returned LLVMValueRef corresponds to a LLVM:Instruction. + * The returned LLVMValueRef corresponds to an LLVM:Instruction. */ LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB); @@ -2324,12 +2412,12 @@ void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, unsigned LLVMCountIncoming(LLVMValueRef PhiNode); /** - * Obtain an incoming value to a PHI node as a LLVMValueRef. + * Obtain an incoming value to a PHI node as an LLVMValueRef. */ LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index); /** - * Obtain an incoming value to a PHI node as a LLVMBasicBlockRef. + * Obtain an incoming value to a PHI node as an LLVMBasicBlockRef. */ LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index); @@ -2520,6 +2608,8 @@ LLVMValueRef LLVMBuildIntToPtr(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildBitCast(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildAddrSpaceCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildZExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildSExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, @@ -2573,9 +2663,9 @@ LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val, const char *Name); LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, - LLVMValueRef PTR, LLVMValueRef Val, - LLVMAtomicOrdering ordering, +LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, + LLVMValueRef PTR, LLVMValueRef Val, + LLVMAtomicOrdering ordering, LLVMBool singleThread); /** @@ -2708,16 +2798,16 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM); initialization succeeded. Must be executed in isolation from all other LLVM api calls. @see llvm::llvm_start_multithreaded */ -LLVMBool LLVMStartMultithreaded(); +LLVMBool LLVMStartMultithreaded(void); /** Deallocate structures necessary to make LLVM safe for multithreading. Must be executed in isolation from all other LLVM api calls. @see llvm::llvm_stop_multithreaded */ -void LLVMStopMultithreaded(); +void LLVMStopMultithreaded(void); /** Check whether LLVM is executing in thread-safe mode or not. @see llvm::llvm_is_multithreaded */ -LLVMBool LLVMIsMultithreaded(); +LLVMBool LLVMIsMultithreaded(void); /** * @} diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index df65a7b..79bcfcd 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -42,7 +42,7 @@ typedef void *LLVMDisasmContextRef; * instruction are specified by the Offset parameter and its byte widith is the * size parameter. For instructions sets with fixed widths and one symbolic * operand per instruction, the Offset parameter will be zero and Size parameter - * will be the instruction width. The information is returned in TagBuf and is + * will be the instruction width. The information is returned in TagBuf and is * Triple specific with its specific information defined by the value of * TagType for that Triple. If symbolic information is returned the function * returns 1, otherwise it returns 0. @@ -58,7 +58,7 @@ typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC, * SubtractSymbol can be link edited independent of each other. Many other * platforms only allow a relocatable expression of the form AddSymbol + Offset * to be encoded. - * + * * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct * LLVMOpInfo1. The value of the relocatable expression for the operand, * including any PC adjustment, is passed in to the call back in the Value @@ -130,6 +130,17 @@ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, /* The output reference is to a cstring address in a literal pool. */ #define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3 +/* The output reference is to a Objective-C CoreFoundation string. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref 4 +/* The output reference is to a Objective-C message. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message 5 +/* The output reference is to a Objective-C message ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref 6 +/* The output reference is to a Objective-C selector ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref 7 +/* The output reference is to a Objective-C class ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref 8 + #ifdef __cplusplus extern "C" { #endif /* !defined(__cplusplus) */ @@ -170,6 +181,10 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DC, uint64_t Options); #define LLVMDisassembler_Option_PrintImmHex 2 /* The option use the other assembler printer variant */ #define LLVMDisassembler_Option_AsmPrinterVariant 4 +/* The option to set comment on instructions */ +#define LLVMDisassembler_Option_SetInstrComments 8 + /* The option to print latency information alongside instructions */ +#define LLVMDisassembler_Option_PrintLatency 16 /** * Dispose of a disassembler context. diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index 50fdb6b..3564312 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -171,6 +171,16 @@ void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); /*===-- Operations on memory managers -------------------------------------===*/ +typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( + void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, + const char *SectionName); +typedef uint8_t *(*LLVMMemoryManagerAllocateDataSectionCallback)( + void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, + const char *SectionName, LLVMBool IsReadOnly); +typedef LLVMBool (*LLVMMemoryManagerFinalizeMemoryCallback)( + void *Opaque, char **ErrMsg); +typedef void (*LLVMMemoryManagerDestroyCallback)(void *Opaque); + /** * Create a simple custom MCJIT memory manager. This memory manager can * intercept allocations in a module-oblivious way. This will return NULL @@ -184,14 +194,10 @@ void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); */ LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( void *Opaque, - uint8_t *(*AllocateCodeSection)(void *Opaque, - uintptr_t Size, unsigned Alignment, - unsigned SectionID), - uint8_t *(*AllocateDataSection)(void *Opaque, - uintptr_t Size, unsigned Alignment, - unsigned SectionID, LLVMBool IsReadOnly), - LLVMBool (*FinalizeMemory)(void *Opaque, char **ErrMsg), - void (*Destroy)(void *Opaque)); + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, + LLVMMemoryManagerDestroyCallback Destroy); void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); @@ -200,7 +206,7 @@ void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); */ #ifdef __cplusplus -} +} #endif /* defined(__cplusplus) */ #endif diff --git a/include/llvm-c/IRReader.h b/include/llvm-c/IRReader.h new file mode 100644 index 0000000..d0a23be --- /dev/null +++ b/include/llvm-c/IRReader.h @@ -0,0 +1,40 @@ +/*===-- llvm-c/IRReader.h - IR Reader C Interface -----------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to the IR Reader. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_IRREADER_H +#define LLVM_C_IRREADER_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Read LLVM IR from a memory buffer and convert it into an in-memory Module + * object. Returns 0 on success. + * Optionally returns a human-readable description of any errors that + * occured during parsing IR. OutMessage must be disposed with + * LLVMDisposeMessage. + * + * @see llvm::ParseIR() + */ +LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + char **OutMessage); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/llvm-c/LinkTimeOptimizer.h b/include/llvm-c/LinkTimeOptimizer.h index 7a0fbf6..8bcf599 100644 --- a/include/llvm-c/LinkTimeOptimizer.h +++ b/include/llvm-c/LinkTimeOptimizer.h @@ -4,7 +4,7 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This header provides a C API to use the LLVM link time optimization @@ -46,7 +46,7 @@ extern "C" { // Added C-specific error codes LLVM_LTO_NULL_OBJECT } llvm_lto_status_t; - + /// This provides C interface to initialize link time optimizer. This allows /// linker to use dlopen() interface to dynamically load LinkTimeOptimizer. /// extern "C" helps, because dlopen() interface uses name to find the symbol. diff --git a/include/llvm-c/Object.h b/include/llvm-c/Object.h index ecccfee..c271552 100644 --- a/include/llvm-c/Object.h +++ b/include/llvm-c/Object.h @@ -100,4 +100,3 @@ const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI); #endif /* defined(__cplusplus) */ #endif - diff --git a/include/llvm-c/Support.h b/include/llvm-c/Support.h new file mode 100644 index 0000000..7f03ede --- /dev/null +++ b/include/llvm-c/Support.h @@ -0,0 +1,35 @@ +/*===-- llvm-c/Support.h - Support C Interface --------------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to the LLVM support library. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_SUPPORT_H +#define LLVM_C_SUPPORT_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This function permanently loads the dynamic library at the given path. + * It is safe to call this function multiple times for the same library. + * + * @see sys::DynamicLibrary::LoadLibraryPermanently() + */ +LLVMBool LLVMLoadLibraryPermanently(const char* Filename); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h index 80fc3e5..b465b4b 100644 --- a/include/llvm-c/Target.h +++ b/include/llvm-c/Target.h @@ -22,6 +22,10 @@ #include "llvm-c/Core.h" #include "llvm/Config/llvm-config.h" +#if defined(_MSC_VER) && !defined(inline) +#define inline __inline +#endif + #ifdef __cplusplus extern "C" { #endif @@ -37,14 +41,13 @@ enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian }; typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; typedef struct LLVMOpaqueTargetLibraryInfotData *LLVMTargetLibraryInfoRef; -typedef struct LLVMStructLayout *LLVMStructLayoutRef; /* Declare all of the target-initialization functions that are available. */ #define LLVM_TARGET(TargetName) \ void LLVMInitialize##TargetName##TargetInfo(void); #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ - + #define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target(void); #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ @@ -53,7 +56,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef; void LLVMInitialize##TargetName##TargetMC(void); #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ - + /* Declare all of the available assembly printer initialization functions. */ #define LLVM_ASM_PRINTER(TargetName) \ void LLVMInitialize##TargetName##AsmPrinter(void); @@ -71,7 +74,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef; void LLVMInitialize##TargetName##Disassembler(void); #include "llvm/Config/Disassemblers.def" #undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */ - + /** LLVMInitializeAllTargetInfos - The main program should call this function if it wants access to all available targets that LLVM is configured to support. */ @@ -98,7 +101,7 @@ static inline void LLVMInitializeAllTargetMCs(void) { #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllAsmPrinters - The main program should call this function if it wants all asm printers that LLVM is configured to support, to make them available via the TargetRegistry. */ @@ -107,7 +110,7 @@ static inline void LLVMInitializeAllAsmPrinters(void) { #include "llvm/Config/AsmPrinters.def" #undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllAsmParsers - The main program should call this function if it wants all asm parsers that LLVM is configured to support, to make them available via the TargetRegistry. */ @@ -116,7 +119,7 @@ static inline void LLVMInitializeAllAsmParsers(void) { #include "llvm/Config/AsmParsers.def" #undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllDisassemblers - The main program should call this function if it wants all disassemblers that LLVM is configured to support, to make them available via the TargetRegistry. */ @@ -126,9 +129,9 @@ static inline void LLVMInitializeAllDisassemblers(void) { #include "llvm/Config/Disassemblers.def" #undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeNativeTarget - The main program should call this function to - initialize the native target corresponding to the host. This is useful + initialize the native target corresponding to the host. This is useful for JIT applications to ensure that the target gets linked in correctly. */ static inline LLVMBool LLVMInitializeNativeTarget(void) { /* If we have a native target, initialize it to ensure it is linked in. */ @@ -140,7 +143,43 @@ static inline LLVMBool LLVMInitializeNativeTarget(void) { #else return 1; #endif -} +} + +/** LLVMInitializeNativeTargetAsmParser - The main program should call this + function to initialize the parser for the native target corresponding to the + host. */ +static inline LLVMBool LLVMInitializeNativeAsmParser(void) { +#ifdef LLVM_NATIVE_ASMPARSER + LLVM_NATIVE_ASMPARSER(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetAsmPrinter - The main program should call this + function to initialize the printer for the native target corresponding to + the host. */ +static inline LLVMBool LLVMInitializeNativeAsmPrinter(void) { +#ifdef LLVM_NATIVE_ASMPRINTER + LLVM_NATIVE_ASMPRINTER(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetDisassembler - The main program should call this + function to initialize the disassembler for the native target corresponding + to the host. */ +static inline LLVMBool LLVMInitializeNativeDisassembler(void) { +#ifdef LLVM_NATIVE_DISASSEMBLER + LLVM_NATIVE_DISASSEMBLER(); + return 0; +#else + return 1; +#endif +} /*===-- Target Data -------------------------------------------------------===*/ @@ -151,83 +190,94 @@ LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep); /** Adds target data information to a pass manager. This does not take ownership of the target data. See the method llvm::PassManagerBase::add. */ -void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef); +void LLVMAddTargetData(LLVMTargetDataRef TD, LLVMPassManagerRef PM); /** Adds target library information to a pass manager. This does not take ownership of the target library info. See the method llvm::PassManagerBase::add. */ -void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef, LLVMPassManagerRef); +void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef TLI, + LLVMPassManagerRef PM); /** Converts target data to a target layout string. The string must be disposed with LLVMDisposeMessage. See the constructor llvm::DataLayout::DataLayout. */ -char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef); +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef TD); /** Returns the byte order of a target, either LLVMBigEndian or LLVMLittleEndian. See the method llvm::DataLayout::isLittleEndian. */ -enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef); +enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef TD); /** Returns the pointer size in bytes for a target. See the method llvm::DataLayout::getPointerSize. */ -unsigned LLVMPointerSize(LLVMTargetDataRef); +unsigned LLVMPointerSize(LLVMTargetDataRef TD); /** Returns the pointer size in bytes for a target for a specified address space. See the method llvm::DataLayout::getPointerSize. */ -unsigned LLVMPointerSizeForAS(LLVMTargetDataRef, unsigned AS); +unsigned LLVMPointerSizeForAS(LLVMTargetDataRef TD, unsigned AS); + +/** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef TD); + +/** Returns the integer type that is the same size as a pointer on a target. + This version allows the address space to be specified. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrTypeForAS(LLVMTargetDataRef TD, unsigned AS); /** Returns the integer type that is the same size as a pointer on a target. See the method llvm::DataLayout::getIntPtrType. */ -LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef); +LLVMTypeRef LLVMIntPtrTypeInContext(LLVMContextRef C, LLVMTargetDataRef TD); /** Returns the integer type that is the same size as a pointer on a target. This version allows the address space to be specified. See the method llvm::DataLayout::getIntPtrType. */ -LLVMTypeRef LLVMIntPtrTypeForAS(LLVMTargetDataRef, unsigned AS); +LLVMTypeRef LLVMIntPtrTypeForASInContext(LLVMContextRef C, LLVMTargetDataRef TD, + unsigned AS); /** Computes the size of a type in bytes for a target. See the method llvm::DataLayout::getTypeSizeInBits. */ -unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the storage size of a type in bytes for a target. See the method llvm::DataLayout::getTypeStoreSize. */ -unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the ABI size of a type in bytes for a target. See the method llvm::DataLayout::getTypeAllocSize. */ -unsigned long long LLVMABISizeOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the ABI alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the call frame alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the preferred alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the preferred alignment of a global variable in bytes for a target. See the method llvm::DataLayout::getPreferredAlignment. */ -unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef, +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef TD, LLVMValueRef GlobalVar); /** Computes the structure element that contains the byte offset for a target. See the method llvm::StructLayout::getElementContainingOffset. */ -unsigned LLVMElementAtOffset(LLVMTargetDataRef, LLVMTypeRef StructTy, +unsigned LLVMElementAtOffset(LLVMTargetDataRef TD, LLVMTypeRef StructTy, unsigned long long Offset); /** Computes the byte offset of the indexed struct element for a target. See the method llvm::StructLayout::getElementContainingOffset. */ -unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef, LLVMTypeRef StructTy, - unsigned Element); +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD, + LLVMTypeRef StructTy, unsigned Element); /** Deallocates a TargetData. See the destructor llvm::DataLayout::~DataLayout. */ -void LLVMDisposeTargetData(LLVMTargetDataRef); +void LLVMDisposeTargetData(LLVMTargetDataRef TD); /** * @} diff --git a/include/llvm-c/TargetMachine.h b/include/llvm-c/TargetMachine.h index 5e35595..e159411 100644 --- a/include/llvm-c/TargetMachine.h +++ b/include/llvm-c/TargetMachine.h @@ -57,11 +57,21 @@ typedef enum { } LLVMCodeGenFileType; /** Returns the first llvm::Target in the registered targets list. */ -LLVMTargetRef LLVMGetFirstTarget(); +LLVMTargetRef LLVMGetFirstTarget(void); /** Returns the next llvm::Target given a previous one (or null if there's none) */ LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T); /*===-- Target ------------------------------------------------------------===*/ +/** Finds the target corresponding to the given name and stores it in \p T. + Returns 0 on success. */ +LLVMTargetRef LLVMGetTargetFromName(const char *Name); + +/** Finds the target corresponding to the given triple and stores it in \p T. + Returns 0 on success. Optionally returns any error in ErrorMessage. + Use LLVMDisposeMessage to dispose the message. */ +LLVMBool LLVMGetTargetFromTriple(const char* Triple, LLVMTargetRef *T, + char **ErrorMessage); + /** Returns the name of a target. See llvm::Target::getName */ const char *LLVMGetTargetName(LLVMTargetRef T); @@ -79,9 +89,9 @@ LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T); /*===-- Target Machine ----------------------------------------------------===*/ /** Creates a new llvm::TargetMachine. See llvm::Target::createTargetMachine */ -LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, char *Triple, - char *CPU, char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, - LLVMCodeModel CodeModel); +LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, + const char *Triple, const char *CPU, const char *Features, + LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel); /** Dispose the LLVMTargetMachineRef instance generated by LLVMCreateTargetMachine. */ @@ -108,6 +118,10 @@ char *LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T); /** Returns the llvm::DataLayout used for this llvm:TargetMachine. */ LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T); +/** Set the target machine's ASM verbosity. */ +void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T, + LLVMBool VerboseAsm); + /** Emits an asm or object file for the given module to the filename. This wraps several c++ only classes (among them a file stream). Returns any error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */ @@ -117,6 +131,12 @@ LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, /** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */ LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf); + +/*===-- Triple ------------------------------------------------------------===*/ +/** Get a triple for the host machine as a string. The result needs to be + disposed with LLVMDisposeMessage. */ +char* LLVMGetDefaultTargetTriple(void); + #ifdef __cplusplus } #endif diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h index a2c4d61..355e8dc 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -65,6 +65,9 @@ void LLVMAddLoopIdiomPass(LLVMPassManagerRef PM); /** See llvm::createLoopRotatePass function. */ void LLVMAddLoopRotatePass(LLVMPassManagerRef PM); +/** See llvm::createLoopRerollPass function. */ +void LLVMAddLoopRerollPass(LLVMPassManagerRef PM); + /** See llvm::createLoopUnrollPass function. */ void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM); @@ -74,6 +77,9 @@ void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM); /** See llvm::createMemCpyOptPass function. */ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); +/** See llvm::createPartiallyInlineLibCallsPass function. */ +void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM); + /** See llvm::createPromoteMemoryToRegisterPass function. */ void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 40110fd..89f54b7 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -16,9 +16,22 @@ #ifndef LLVM_C_LTO_H #define LLVM_C_LTO_H -#include <stdbool.h> #include <stddef.h> -#include <unistd.h> +#include <sys/types.h> + +#ifndef __cplusplus +#if !defined(_MSC_VER) +#include <stdbool.h> +typedef bool lto_bool_t; +#else +/* MSVC in particular does not have anything like _Bool or bool in C, but we can + at least make sure the type is the same size. The implementation side will + use C++ bool. */ +typedef unsigned char lto_bool_t; +#endif +#else +typedef bool lto_bool_t; +#endif /** * @defgroup LLVMCLTO LTO @@ -27,7 +40,7 @@ * @{ */ -#define LTO_API_VERSION 4 +#define LTO_API_VERSION 5 typedef enum { LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ @@ -87,14 +100,14 @@ lto_get_error_message(void); /** * Checks if a file is a loadable object file. */ -extern bool +extern lto_bool_t lto_module_is_object_file(const char* path); /** * Checks if a file is a loadable object compiled for requested target. */ -extern bool +extern lto_bool_t lto_module_is_object_file_for_target(const char* path, const char* target_triple_prefix); @@ -102,14 +115,14 @@ lto_module_is_object_file_for_target(const char* path, /** * Checks if a buffer is a loadable object file. */ -extern bool +extern lto_bool_t lto_module_is_object_file_in_memory(const void* mem, size_t length); /** * Checks if a buffer is a loadable object compiled for requested target. */ -extern bool +extern lto_bool_t lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, const char* target_triple_prefix); @@ -208,7 +221,7 @@ lto_codegen_dispose(lto_code_gen_t); * Add an object module to the set of modules for which code will be generated. * Returns true on error (check lto_get_error_message() for details). */ -extern bool +extern lto_bool_t lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); @@ -217,7 +230,7 @@ lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); * Sets if debug info should be generated. * Returns true on error (check lto_get_error_message() for details). */ -extern bool +extern lto_bool_t lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); @@ -225,7 +238,7 @@ lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); * Sets which PIC code model to generated. * Returns true on error (check lto_get_error_message() for details). */ -extern bool +extern lto_bool_t lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model); @@ -251,9 +264,8 @@ lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, int nargs); /** - * Adds to a list of all global symbols that must exist in the final - * generated code. If a function is not listed, it might be - * inlined into every usage and optimized away. + * Tells LTO optimization passes that this symbol must be preserved + * because it is referenced by native code or a command line option. */ extern void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); @@ -263,7 +275,7 @@ lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); * merged contents of all modules added so far. * Returns true on error (check lto_get_error_message() for details). */ -extern bool +extern lto_bool_t lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); /** @@ -281,7 +293,7 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); * Generates code for all added modules into one native object file. * The name of the file is written to name. Returns true on error. */ -extern bool +extern lto_bool_t lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 625a6db..d494ad2 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -765,7 +765,9 @@ public: return APInt(getBitWidth(), VAL & RHS.VAL); return AndSlowCase(RHS); } - APInt And(const APInt &RHS) const { return this->operator&(RHS); } + APInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APInt &RHS) const { + return this->operator&(RHS); + } /// \brief Bitwise OR operator. /// @@ -785,7 +787,9 @@ public: /// calling operator|. /// /// \returns An APInt value representing the bitwise OR of *this and RHS. - APInt Or(const APInt &RHS) const { return this->operator|(RHS); } + APInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APInt &RHS) const { + return this->operator|(RHS); + } /// \brief Bitwise XOR operator. /// @@ -805,7 +809,9 @@ public: /// through the usage of operator^. /// /// \returns An APInt value representing the bitwise XOR of *this and RHS. - APInt Xor(const APInt &RHS) const { return this->operator^(RHS); } + APInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APInt &RHS) const { + return this->operator^(RHS); + } /// \brief Multiplication operator. /// @@ -837,17 +843,17 @@ public: /// \brief Arithmetic right-shift function. /// /// Arithmetic right-shift this APInt by shiftAmt. - APInt ashr(unsigned shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(unsigned shiftAmt) const; /// \brief Logical right-shift function. /// /// Logical right-shift this APInt by shiftAmt. - APInt lshr(unsigned shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(unsigned shiftAmt) const; /// \brief Left-shift function. /// /// Left-shift this APInt by shiftAmt. - APInt shl(unsigned shiftAmt) const { + APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(unsigned shiftAmt) const { assert(shiftAmt <= BitWidth && "Invalid shift amount"); if (isSingleWord()) { if (shiftAmt >= BitWidth) @@ -858,31 +864,31 @@ public: } /// \brief Rotate left by rotateAmt. - APInt rotl(unsigned rotateAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(unsigned rotateAmt) const; /// \brief Rotate right by rotateAmt. - APInt rotr(unsigned rotateAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(unsigned rotateAmt) const; /// \brief Arithmetic right-shift function. /// /// Arithmetic right-shift this APInt by shiftAmt. - APInt ashr(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(const APInt &shiftAmt) const; /// \brief Logical right-shift function. /// /// Logical right-shift this APInt by shiftAmt. - APInt lshr(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(const APInt &shiftAmt) const; /// \brief Left-shift function. /// /// Left-shift this APInt by shiftAmt. - APInt shl(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(const APInt &shiftAmt) const; /// \brief Rotate left by rotateAmt. - APInt rotl(const APInt &rotateAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(const APInt &rotateAmt) const; /// \brief Rotate right by rotateAmt. - APInt rotr(const APInt &rotateAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(const APInt &rotateAmt) const; /// \brief Unsigned division operation. /// @@ -890,12 +896,12 @@ public: /// RHS are treated as unsigned quantities for purposes of this division. /// /// \returns a new APInt value containing the division result - APInt udiv(const APInt &RHS) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT udiv(const APInt &RHS) const; /// \brief Signed division function for APInt. /// /// Signed divide this APInt by APInt RHS. - APInt sdiv(const APInt &RHS) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sdiv(const APInt &RHS) const; /// \brief Unsigned remainder operation. /// @@ -906,12 +912,12 @@ public: /// is *this. /// /// \returns a new APInt value containing the remainder result - APInt urem(const APInt &RHS) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT urem(const APInt &RHS) const; /// \brief Function for signed remainder operation. /// /// Signed remainder operation on APInt. - APInt srem(const APInt &RHS) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT srem(const APInt &RHS) const; /// \brief Dual division/remainder interface. /// @@ -1145,7 +1151,7 @@ public: /// /// Truncate the APInt to a specified width. It is an error to specify a width /// that is greater than or equal to the current width. - APInt trunc(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(unsigned width) const; /// \brief Sign extend to a new width. /// @@ -1153,38 +1159,38 @@ public: /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. /// It is an error to specify a width that is less than or equal to the /// current width. - APInt sext(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sext(unsigned width) const; /// \brief Zero extend to a new width. /// /// This operation zero extends the APInt to a new width. The high order bits /// are filled with 0 bits. It is an error to specify a width that is less /// than or equal to the current width. - APInt zext(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zext(unsigned width) const; /// \brief Sign extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is sign /// extended, truncated, or left alone to make it that width. - APInt sextOrTrunc(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrTrunc(unsigned width) const; /// \brief Zero extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is zero /// extended, truncated, or left alone to make it that width. - APInt zextOrTrunc(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrTrunc(unsigned width) const; /// \brief Sign extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is sign /// extended, or left alone to make it that width. - APInt sextOrSelf(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrSelf(unsigned width) const; /// \brief Zero extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is zero /// extended, or left alone to make it that width. - APInt zextOrSelf(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrSelf(unsigned width) const; /// @} /// \name Bit Manipulation Operators @@ -1421,7 +1427,7 @@ public: std::string toString(unsigned Radix, bool Signed) const; /// \returns a byte-swapped representation of this APInt Value. - APInt byteSwap() const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const; /// \brief Converts this APInt to a double value. double roundToDouble(bool isSigned) const; @@ -1464,7 +1470,7 @@ public: /// /// The conversion does not do a translation from double to integer, it just /// re-interprets the bits of the double. - static APInt doubleToBits(double V) { + static APInt LLVM_ATTRIBUTE_UNUSED_RESULT doubleToBits(double V) { union { uint64_t I; double D; @@ -1477,7 +1483,7 @@ public: /// /// The conversion does not do a translation from float to integer, it just /// re-interprets the bits of the float. - static APInt floatToBits(float V) { + static APInt LLVM_ATTRIBUTE_UNUSED_RESULT floatToBits(float V) { union { unsigned I; float F; @@ -1507,12 +1513,12 @@ public: } /// \brief Compute the square root - APInt sqrt() const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sqrt() const; /// \brief Get the absolute value; /// /// If *this is < 0 then return -(*this), otherwise *this; - APInt abs() const { + APInt LLVM_ATTRIBUTE_UNUSED_RESULT abs() const { if (isNegative()) return -(*this); return *this; diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 11be4c5..ad035a7 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -68,18 +68,18 @@ public: } using APInt::toString; - APSInt trunc(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { return APSInt(APInt::trunc(width), IsUnsigned); } - APSInt extend(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { if (IsUnsigned) return APSInt(zext(width), IsUnsigned); else return APSInt(sext(width), IsUnsigned); } - APSInt extOrTrunc(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const { if (IsUnsigned) return APSInt(zextOrTrunc(width), IsUnsigned); else @@ -212,7 +212,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); } - APSInt And(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { return this->operator&(RHS); } @@ -220,7 +220,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); } - APSInt Or(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { return this->operator|(RHS); } @@ -229,7 +229,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); } - APSInt Xor(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const { return this->operator^(RHS); } diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index d4152ec..e5562c3 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -80,9 +80,16 @@ namespace llvm { /// Construct an ArrayRef from a C array. template <size_t N> - /*implicit*/ ArrayRef(const T (&Arr)[N]) + /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} +#if LLVM_HAS_INITIALIZER_LISTS + /// Construct an ArrayRef from a std::initializer_list. + /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec) + : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()), + Length(Vec.size()) {} +#endif + /// @} /// @name Simple Operations /// @{ @@ -178,6 +185,8 @@ namespace llvm { public: typedef T *iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + /// Construct an empty MutableArrayRef. /*implicit*/ MutableArrayRef() : ArrayRef<T>() {} @@ -212,6 +221,9 @@ namespace llvm { iterator begin() const { return data(); } iterator end() const { return data() + this->size(); } + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + /// front - Get the first element. T &front() const { assert(!this->empty()); diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index d5aa864..ce322cc 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -64,7 +64,9 @@ public: return const_iterator(getBucketsEnd(), getBucketsEnd(), true); } - bool empty() const { return getNumEntries() == 0; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return getNumEntries() == 0; + } unsigned size() const { return getNumEntries(); } /// Grow the densemap so that it has at least Size buckets. Does not shrink @@ -436,9 +438,8 @@ private: this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); NumBuckets = getNumBuckets(); - } - if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { - this->grow(NumBuckets * 2); + } else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { + this->grow(NumBuckets); LookupBucketFor(Key, TheBucket); } assert(TheBucket); @@ -713,13 +714,13 @@ public: init(NumInitBuckets); } - SmallDenseMap(const SmallDenseMap &other) { + SmallDenseMap(const SmallDenseMap &other) : BaseT() { init(0); copyFrom(other); } #if LLVM_HAS_RVALUE_REFERENCES - SmallDenseMap(SmallDenseMap &&other) { + SmallDenseMap(SmallDenseMap &&other) : BaseT() { init(0); swap(other); } diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index a667479..8f8fb98 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -211,6 +211,7 @@ public: friend class ImmutableMap; public: + typedef ptrdiff_t difference_type; typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type value_type; typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type_ref reference; typedef typename iterator::value_type *pointer; diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index fbdf066..ad34969 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -851,6 +851,18 @@ PROFILE_INTEGER_INFO(unsigned long long) #undef PROFILE_INTEGER_INFO +/// Profile traits for booleans. +template <> +struct ImutProfileInfo<bool> { + typedef const bool value_type; + typedef const bool& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + ID.AddBoolean(X); + } +}; + + /// Generic profile trait for pointer types. We treat pointers as /// references to unique objects. template <typename T> @@ -1060,6 +1072,7 @@ public: friend class ImmutableSet<ValT,ValInfo>; public: + typedef ptrdiff_t difference_type; typedef typename ImmutableSet<ValT,ValInfo>::value_type value_type; typedef typename ImmutableSet<ValT,ValInfo>::value_type_ref reference; typedef typename iterator::value_type *pointer; diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 0299a83..0cfd470 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_POINTERINTPAIR_H #define LLVM_ADT_POINTERINTPAIR_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> @@ -40,7 +41,7 @@ template <typename PointerTy, unsigned IntBits, typename IntType=unsigned, typename PtrTraits = PointerLikeTypeTraits<PointerTy> > class PointerIntPair { intptr_t Value; - enum { + enum LLVM_ENUM_INT_TYPE(uintptr_t) { /// PointerBitMask - The bits that come from the pointer. PointerBitMask = ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index c1a6d74..05d362f 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -72,7 +72,7 @@ namespace llvm { /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" /// X = P.get<int*>(); // ok. /// Y = P.get<float*>(); // runtime assertion failure. - /// Z = P.get<double*>(); // runtime assertion failure (regardless of tag) + /// Z = P.get<double*>(); // compile time failure. /// P = (float*)0; /// Y = P.get<float*>(); // ok. /// X = P.get<int*>(); // runtime assertion failure. @@ -177,10 +177,17 @@ namespace llvm { }; template<typename PT1, typename PT2> - bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) { + static bool operator==(PointerUnion<PT1, PT2> lhs, + PointerUnion<PT1, PT2> rhs) { return lhs.getOpaqueValue() == rhs.getOpaqueValue(); } - + + template<typename PT1, typename PT2> + static bool operator!=(PointerUnion<PT1, PT2> lhs, + PointerUnion<PT1, PT2> rhs) { + return lhs.getOpaqueValue() != rhs.getOpaqueValue(); + } + // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits)-1. template<typename PT1, typename PT2> diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index dacda36..3aa8183 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -217,6 +217,22 @@ inline tier<T1, T2> tie(T1& f, T2& s) { return tier<T1, T2>(f, s); } +/// \brief Function object to check whether the first component of a std::pair +/// compares less than the first component of another std::pair. +struct less_first { + template <typename T> bool operator()(const T &lhs, const T &rhs) const { + return lhs.first < rhs.first; + } +}; + +/// \brief Function object to check whether the second component of a std::pair +/// compares less than the second component of another std::pair. +struct less_second { + template <typename T> bool operator()(const T &lhs, const T &rhs) const { + return lhs.second < rhs.second; + } +}; + //===----------------------------------------------------------------------===// // Extra additions for arrays //===----------------------------------------------------------------------===// @@ -277,12 +293,16 @@ inline void array_pod_sort(IteratorTy Start, IteratorTy End) { get_array_pod_sort_comparator(*Start)); } -template<class IteratorTy> -inline void array_pod_sort(IteratorTy Start, IteratorTy End, - int (*Compare)(const void*, const void*)) { +template <class IteratorTy> +inline void array_pod_sort( + IteratorTy Start, IteratorTy End, + int (*Compare)( + const typename std::iterator_traits<IteratorTy>::value_type *, + const typename std::iterator_traits<IteratorTy>::value_type *)) { // Don't dereference start iterator of empty sequence. if (Start == End) return; - qsort(&*Start, End-Start, sizeof(*Start), Compare); + qsort(&*Start, End - Start, sizeof(*Start), + reinterpret_cast<int (*)(const void *, const void *)>(Compare)); } //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index d2f7286..5eda37c 100644 --- a/include/llvm/ADT/SetVector.h +++ b/include/llvm/ADT/SetVector.h @@ -170,7 +170,7 @@ public: vector_.pop_back(); } - T pop_back_val() { + T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { T Ret = back(); pop_back(); return Ret; diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 8c73041..bd0d883 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -71,7 +71,7 @@ protected: ~SmallPtrSetImpl(); public: - bool empty() const { return size() == 0; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } unsigned size() const { return NumElements; } void clear() { diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 7ba0a71..505aa8d 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -53,7 +53,7 @@ public: return size_t((char*)CapacityX - (char*)BeginX); } - bool empty() const { return BeginX == EndX; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } }; template <typename T, unsigned N> struct SmallVectorStorage; @@ -427,7 +427,7 @@ public: this->grow(N); } - T pop_back_val() { + T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { #if LLVM_HAS_RVALUE_REFERENCES T Result = ::std::move(this->back()); #else diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index d2887c5..56dbb5b 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H +#include <iterator> #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" @@ -159,6 +160,48 @@ static inline StringRef getOrdinalSuffix(unsigned Val) { } } +template <typename IteratorT> +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::input_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +template <typename IteratorT> +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::forward_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); + for (IteratorT I = Begin; I != End; ++I) + Len += (*Begin).size(); + S.reserve(Len); + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +/// Joins the strings in the range [Begin, End), adding Separator between +/// the elements. +template <typename IteratorT> +inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) { + typedef typename std::iterator_traits<IteratorT>::iterator_category tag; + return join_impl(Begin, End, Separator, tag()); +} + } // End llvm namespace #endif diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 3e1e24c..ec0c284 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -175,7 +175,7 @@ namespace llvm { /// transform one of the given strings into the other. If zero, /// the strings are identical. unsigned edit_distance(StringRef Other, bool AllowReplacements = true, - unsigned MaxEditDistance = 0); + unsigned MaxEditDistance = 0) const; /// str - Get the contents as an std::string. std::string str() const { @@ -210,12 +210,18 @@ namespace llvm { compareMemory(Data, Prefix.Data, Prefix.Length) == 0; } + /// Check if this string starts with the given \p Prefix, ignoring case. + bool startswith_lower(StringRef Prefix) const; + /// Check if this string ends with the given \p Suffix. bool endswith(StringRef Suffix) const { return Length >= Suffix.Length && compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; } + /// Check if this string ends with the given \p Suffix, ignoring case. + bool endswith_lower(StringRef Suffix) const; + /// @} /// @name String Searching /// @{ diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 8d968e8..84e0b29 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -14,6 +14,7 @@ // Some system headers or GCC predefined macros conflict with identifiers in // this file. Undefine them here. +#undef NetBSD #undef mips #undef sparc @@ -318,7 +319,12 @@ public: return getOS() == Triple::Cygwin || getOS() == Triple::MinGW32; } - /// isOSWindows - Is this a "Windows" OS. + /// \brief Is this a "Windows" OS targeting a "MSVCRT.dll" environment. + bool isOSMSVCRT() const { + return getOS() == Triple::Win32 || getOS() == Triple::MinGW32; + } + + /// \brief Tests whether the OS is Windows. bool isOSWindows() const { return getOS() == Triple::Win32 || isOSCygMing(); } @@ -328,6 +334,11 @@ public: return getOS() == Triple::NaCl; } + /// \brief Tests whether the OS is Linux. + bool isOSLinux() const { + return getOS() == Triple::Linux; + } + /// \brief Tests whether the OS uses the ELF binary format. bool isOSBinFormatELF() const { return !isOSDarwin() && !isOSWindows(); diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 71dab2e..6aeaa91 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -382,7 +382,9 @@ public: // Miscellaneous inspection routines. size_type max_size() const { return size_type(-1); } - bool empty() const { return Head == 0 || Head == getTail(); } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return Head == 0 || Head == getTail(); + } // Front and back accessor functions... reference front() { @@ -534,7 +536,7 @@ public: // Functionality derived from other functions defined above... // - size_type size() const { + size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const { if (Head == 0) return 0; // Don't require construction of sentinel if empty. return std::distance(begin(), end()); } diff --git a/include/llvm/ADT/polymorphic_ptr.h b/include/llvm/ADT/polymorphic_ptr.h new file mode 100644 index 0000000..b8d8d71 --- /dev/null +++ b/include/llvm/ADT/polymorphic_ptr.h @@ -0,0 +1,117 @@ +//===- llvm/ADT/polymorphic_ptr.h - Smart copyable owned ptr ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides a polymorphic_ptr class template. See the class comments +/// for details about this API, its intended use cases, etc. +/// +/// The primary motivation here is to work around the necessity of copy +/// semantics in C++98. This is typically used where any actual copies are +/// incidental or unnecessary. As a consequence, it is expected to cease to be +/// useful and be removed when we can directly rely on move-only types. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POLYMORPHIC_PTR_H +#define LLVM_ADT_POLYMORPHIC_PTR_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + +/// \brief An owning, copyable polymorphic smart pointer. +/// +/// This pointer exists to provide copyable owned smart pointer. Rather than +/// shared ownership semantics, it has unique ownership semantics and deep copy +/// semantics. It is copyable by requiring that the underlying type exposes +/// a method which can produce a (heap allocated) clone. +/// +/// Note that in almost all scenarios use of this could be avoided if we could +/// build move-only containers of a std::unique_ptr, but until then this +/// provides an effective way to place polymorphic objects in a container. +template <typename T> class polymorphic_ptr { + T *ptr; + +public: + polymorphic_ptr(T *ptr = 0) : ptr(ptr) {} + polymorphic_ptr(const polymorphic_ptr &arg) : ptr(arg ? arg->clone() : 0) {} +#if LLVM_HAS_RVALUE_REFERENCES + polymorphic_ptr(polymorphic_ptr &&arg) : ptr(arg.take()) {} +#endif + ~polymorphic_ptr() { delete ptr; } + + polymorphic_ptr &operator=(polymorphic_ptr arg) { + swap(arg); + return *this; + } + polymorphic_ptr &operator=(T *arg) { + if (arg != ptr) { + delete ptr; + ptr = arg; + } + return *this; + } + + T &operator*() const { return *ptr; } + T *operator->() const { return ptr; } + LLVM_EXPLICIT operator bool() const { return ptr != 0; } + bool operator!() const { return ptr == 0; } + + T *get() const { return ptr; } + + T *take() { + T *tmp = ptr; + ptr = 0; + return tmp; + } + + void swap(polymorphic_ptr &arg) { + T *tmp = ptr; + ptr = arg.ptr; + arg.ptr = tmp; + } +}; + +template <typename T> +void swap(polymorphic_ptr<T> &lhs, polymorphic_ptr<T> &rhs) { + lhs.swap(rhs); +} + +template <typename T, typename U> +bool operator==(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) { + return lhs.get() == rhs.get(); +} + +template <typename T, typename U> +bool operator!=(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) { + return lhs.get() != rhs.get(); +} + +template <typename T, typename U> +bool operator==(const polymorphic_ptr<T> &lhs, U *rhs) { + return lhs.get() == rhs; +} + +template <typename T, typename U> +bool operator!=(const polymorphic_ptr<T> &lhs, U *rhs) { + return lhs.get() != rhs; +} + +template <typename T, typename U> +bool operator==(T *lhs, const polymorphic_ptr<U> &rhs) { + return lhs == rhs.get(); +} + +template <typename T, typename U> +bool operator!=(T *lhs, const polymorphic_ptr<U> &rhs) { + return lhs != rhs.get(); +} + +} + +#endif diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h index 5e14d6f..817a441 100644 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -118,7 +118,7 @@ class BlockFrequencyImpl { /// isBackedge - Return if edge Src -> Dst is a reachable backedge. /// - bool isBackedge(BlockT *Src, BlockT *Dst) { + bool isBackedge(BlockT *Src, BlockT *Dst) const { unsigned a = RPO.lookup(Src); if (!a) return false; diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index 64bd15c..a123d0b 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -41,6 +41,8 @@ public: bool runOnFunction(Function &F); void print(raw_ostream &O, const Module *M) const; + const Function *getFunction() const; + void view() const; /// getblockFreq - Return block frequency. Return 0 if we don't have the /// information. Please note that initial frequency is equal to ENTRY_FREQ. It diff --git a/include/llvm/Analysis/CFG.h b/include/llvm/Analysis/CFG.h index 08fdc26..e5683c8 100644 --- a/include/llvm/Analysis/CFG.h +++ b/include/llvm/Analysis/CFG.h @@ -49,6 +49,9 @@ unsigned GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ); bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, bool AllowIdenticalEdges = false); +/// \brief Determine whether instruction 'To' is reachable from 'From', +/// returning true if uncertain. +/// /// Determine whether there is a path from From to To within a single function. /// Returns false only if we can prove that once 'From' has been executed then /// 'To' can not be executed. Conservatively returns true. @@ -62,7 +65,18 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, /// on branchy code but not loops, and LI is most useful on code with loops but /// does not help on branchy code outside loops. bool isPotentiallyReachable(const Instruction *From, const Instruction *To, - DominatorTree *DT = 0, LoopInfo *LI = 0); + const DominatorTree *DT = 0, + const LoopInfo *LI = 0); + +/// \brief Determine whether block 'To' is reachable from 'From', returning +/// true if uncertain. +/// +/// Determine whether there is a path from From to To within a single function. +/// Returns false only if we can prove that once 'From' has been reached then +/// 'To' can not be executed. Conservatively returns true. +bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To, + const DominatorTree *DT = 0, + const LoopInfo *LI = 0); } // End llvm namespace diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index fa596c3..39e90eb 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -44,8 +44,9 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { return OS.str(); } - static std::string getCompleteNodeLabel(const BasicBlock *Node, + static std::string getCompleteNodeLabel(const BasicBlock *Node, const Function *) { + enum { MaxColumns = 80 }; std::string Str; raw_string_ostream OS(Str); @@ -59,16 +60,32 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); // Process string output to make it nicer... - for (unsigned i = 0; i != OutStr.length(); ++i) + unsigned ColNum = 0; + unsigned LastSpace = 0; + for (unsigned i = 0; i != OutStr.length(); ++i) { if (OutStr[i] == '\n') { // Left justify OutStr[i] = '\\'; OutStr.insert(OutStr.begin()+i+1, 'l'); + ColNum = 0; + LastSpace = 0; } else if (OutStr[i] == ';') { // Delete comments! unsigned Idx = OutStr.find('\n', i+1); // Find end of line OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); --i; + } else if (ColNum == MaxColumns) { // Wrap lines. + if (LastSpace) { + OutStr.insert(LastSpace, "\\l..."); + ColNum = i - LastSpace; + LastSpace = 0; + i += 3; // The loop will advance 'i' again. + } + // Else keep trying to find a space. } - + else + ++ColNum; + if (OutStr[i] == ' ') + LastSpace = i; + } return OutStr; } @@ -86,20 +103,20 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator())) if (BI->isConditional()) return (I == succ_begin(Node)) ? "T" : "F"; - + // Label source of switch edges with the associated value. if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) { unsigned SuccNo = I.getSuccessorIndex(); if (SuccNo == 0) return "def"; - + std::string Str; raw_string_ostream OS(Str); SwitchInst::ConstCaseIt Case = - SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); + SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); OS << Case.getCaseValue()->getValue(); return OS.str(); - } + } return ""; } }; diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 591484d..d00c2ed 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -69,13 +69,36 @@ class CallGraphNode; //===----------------------------------------------------------------------===// // CallGraph class definition // -class CallGraph { -protected: +class CallGraph : public ModulePass { Module *Mod; // The module this call graph represents typedef std::map<const Function *, CallGraphNode *> FunctionMapTy; FunctionMapTy FunctionMap; // Map from a function to its node + // Root is root of the call graph, or the external node if a 'main' function + // couldn't be found. + // + CallGraphNode *Root; + + // ExternalCallingNode - This node has edges to all external functions and + // those internal functions that have their address taken. + CallGraphNode *ExternalCallingNode; + + // CallsExternalNode - This node has edges to it from all functions making + // indirect calls or calling an external function. + CallGraphNode *CallsExternalNode; + + /// Replace the function represented by this node by another. + /// This does not rescan the body of the function, so it is suitable when + /// splicing the body of one function to another while also updating all + /// callers from the old function to the new. + /// + void spliceFunction(const Function *From, const Function *To); + + // Add a function to the call graph, and link the node to all of the functions + // that it calls. + void addToCallGraph(Function *F); + public: static char ID; // Class identification, replacement for typeinfo //===--------------------------------------------------------------------- @@ -107,15 +130,14 @@ public: } /// Returns the CallGraphNode which is used to represent undetermined calls - /// into the callgraph. Override this if you want behavioral inheritance. - virtual CallGraphNode* getExternalCallingNode() const { return 0; } - virtual CallGraphNode* getCallsExternalNode() const { return 0; } + /// into the callgraph. + CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; } + CallGraphNode *getCallsExternalNode() const { return CallsExternalNode; } /// Return the root/main method in the module, or some other root node, such - /// as the externalcallingnode. Overload these if you behavioral - /// inheritance. - virtual CallGraphNode* getRoot() { return 0; } - virtual const CallGraphNode* getRoot() const { return 0; } + /// as the externalcallingnode. + CallGraphNode *getRoot() { return Root; } + const CallGraphNode *getRoot() const { return Root; } //===--------------------------------------------------------------------- // Functions to keep a call graph up to date with a function that has been @@ -129,41 +151,20 @@ public: /// do this is to dropAllReferences before calling this. /// Function *removeFunctionFromModule(CallGraphNode *CGN); - Function *removeFunctionFromModule(Function *F) { - return removeFunctionFromModule((*this)[F]); - } /// getOrInsertFunction - This method is identical to calling operator[], but /// it will insert a new CallGraphNode for the specified function if one does /// not already exist. CallGraphNode *getOrInsertFunction(const Function *F); - /// spliceFunction - Replace the function represented by this node by another. - /// This does not rescan the body of the function, so it is suitable when - /// splicing the body of one function to another while also updating all - /// callers from the old function to the new. - /// - void spliceFunction(const Function *From, const Function *To); - - //===--------------------------------------------------------------------- - // Pass infrastructure interface glue code. - // -protected: - CallGraph() {} - -public: - virtual ~CallGraph() { destroy(); } - - /// initialize - Call this method before calling other methods, - /// re/initializes the state of the CallGraph. - /// - void initialize(Module &M); + CallGraph(); + virtual ~CallGraph() { releaseMemory(); } + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual bool runOnModule(Module &M); + virtual void releaseMemory(); - void print(raw_ostream &o, Module *) const; + void print(raw_ostream &o, const Module *) const; void dump() const; -protected: - // destroy - Release memory for the call graph - virtual void destroy(); }; //===----------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 8fce2f6..ea8cecf 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -908,6 +908,10 @@ namespace llvm { /// based on the current constraint. void updateDirection(Dependence::DVEntry &Level, const Constraint &CurConstraint) const; + + bool tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV, + SmallVectorImpl<Subscript> &Pair) const; + public: static char ID; // Class identification, replacement for typeinfo DependenceAnalysis() : FunctionPass(ID) { diff --git a/include/llvm/Analysis/Dominators.h b/include/llvm/Analysis/Dominators.h index 81c04bb..3aa0beb 100644 --- a/include/llvm/Analysis/Dominators.h +++ b/include/llvm/Analysis/Dominators.h @@ -346,6 +346,20 @@ public: DomTreeNodeBase<NodeT> *getRootNode() { return RootNode; } const DomTreeNodeBase<NodeT> *getRootNode() const { return RootNode; } + /// Get all nodes dominated by R, including R itself. Return true on success. + void getDescendants(NodeT *R, SmallVectorImpl<NodeT *> &Result) const { + const DomTreeNodeBase<NodeT> *RN = getNode(R); + SmallVector<const DomTreeNodeBase<NodeT> *, 8> WL; + WL.push_back(RN); + Result.clear(); + + while (!WL.empty()) { + const DomTreeNodeBase<NodeT> *N = WL.pop_back_val(); + Result.push_back(N->getBlock()); + WL.append(N->begin(), N->end()); + } + } + /// properlyDominates - Returns true iff A dominates B and A != B. /// Note that this is not a constant time operation! /// @@ -755,6 +769,12 @@ public: return DT->getRootNode(); } + /// Get all nodes dominated by R, including R itself. Return true on success. + void getDescendants(BasicBlock *R, + SmallVectorImpl<BasicBlock *> &Result) const { + DT->getDescendants(R, Result); + } + /// compare - Return false if the other dominator tree matches this /// dominator tree. Otherwise return true. inline bool compare(DominatorTree &Other) const { diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 7b3eed7..62f5aca 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -69,6 +69,8 @@ class LoopBase { // Blocks - The list of blocks in this loop. First entry is the header node. std::vector<BlockT*> Blocks; + SmallPtrSet<const BlockT*, 8> DenseBlockSet; + LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; const LoopBase<BlockT, LoopT>& operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; @@ -108,7 +110,7 @@ public: /// contains - Return true if the specified basic block is in this loop. /// bool contains(const BlockT *BB) const { - return std::find(block_begin(), block_end(), BB) != block_end(); + return DenseBlockSet.count(BB); } /// contains - Return true if the specified instruction is in this loop. @@ -134,7 +136,6 @@ public: /// getBlocks - Get a list of the basic blocks which make up this loop. /// const std::vector<BlockT*> &getBlocks() const { return Blocks; } - std::vector<BlockT*> &getBlocksVector() { return Blocks; } typedef typename std::vector<BlockT*>::const_iterator block_iterator; block_iterator block_begin() const { return Blocks.begin(); } block_iterator block_end() const { return Blocks.end(); } @@ -271,6 +272,17 @@ public: /// transformations should use addBasicBlockToLoop. void addBlockEntry(BlockT *BB) { Blocks.push_back(BB); + DenseBlockSet.insert(BB); + } + + /// reverseBlocks - interface to reverse Blocks[from, end of loop] in this loop + void reverseBlock(unsigned from) { + std::reverse(Blocks.begin() + from, Blocks.end()); + } + + /// reserveBlocks- interface to do reserve() for Blocks + void reserveBlocks(unsigned size) { + Blocks.reserve(size); } /// moveToHeader - This method is used to move BB (which must be part of this @@ -293,6 +305,7 @@ public: /// the mapping in the LoopInfo class. void removeBlockFromLoop(BlockT *BB) { RemoveFromVector(Blocks, BB); + DenseBlockSet.erase(BB); } /// verifyLoop - Verify loop structure @@ -307,6 +320,7 @@ protected: friend class LoopInfoBase<BlockT, LoopT>; explicit LoopBase(BlockT *BB) : ParentLoop(0) { Blocks.push_back(BB); + DenseBlockSet.insert(BB); } }; diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 5485f3c..c98cb58 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -31,17 +31,12 @@ namespace llvm { template<class BlockT, class LoopT> void LoopBase<BlockT, LoopT>:: getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - typedef GraphTraits<BlockT*> BlockTraits; for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) for (typename BlockTraits::ChildIteratorType I = BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) { + if (!contains(*I)) { // Not in current loop? It must be an exit block. ExitingBlocks.push_back(*BI); break; @@ -65,17 +60,12 @@ BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const { template<class BlockT, class LoopT> void LoopBase<BlockT, LoopT>:: getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - typedef GraphTraits<BlockT*> BlockTraits; for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) for (typename BlockTraits::ChildIteratorType I = BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + if (!contains(*I)) // Not in current loop? It must be an exit block. ExitBlocks.push_back(*I); } @@ -95,17 +85,12 @@ BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const { template<class BlockT, class LoopT> void LoopBase<BlockT, LoopT>:: getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); - array_pod_sort(LoopBBs.begin(), LoopBBs.end()); - typedef GraphTraits<BlockT*> BlockTraits; for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) for (typename BlockTraits::ChildIteratorType I = BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + if (!contains(*I)) // Not in current loop? It must be an exit block. ExitEdges.push_back(Edge(*BI, *I)); } @@ -210,7 +195,7 @@ addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) { // Add the basic block to this loop and all parent loops... while (L) { - L->Blocks.push_back(NewBB); + L->addBlockEntry(NewBB); L = L->getParentLoop(); } } @@ -250,11 +235,6 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const { // Keep track of the number of BBs visited. unsigned NumVisited = 0; - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - // Check the individual blocks. for ( ; BI != BE; ++BI) { BlockT *BB = *BI; @@ -266,7 +246,7 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const { for (typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB); SI != SE; ++SI) - if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) { + if (contains(*SI)) { HasInsideLoopSuccs = true; break; } @@ -275,7 +255,7 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const { InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB); PI != PE; ++PI) { BlockT *N = *PI; - if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N)) + if (contains(N)) HasInsideLoopPreds = true; else OutsideLoopPreds.push_back(N); @@ -309,7 +289,7 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const { // Each block in each subloop should be contained within this loop. for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end(); BI != BE; ++BI) { - assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) && + assert(contains(*BI) && "Loop does not contain all the blocks of a subloop!"); } @@ -418,7 +398,7 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges, } } L->getSubLoopsVector().reserve(NumSubloops); - L->getBlocksVector().reserve(NumBlocks); + L->reserveBlocks(NumBlocks); } namespace { @@ -489,15 +469,14 @@ void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) { // For convenience, Blocks and Subloops are inserted in postorder. Reverse // the lists, except for the loop header, which is always at the beginning. - std::reverse(Subloop->getBlocksVector().begin()+1, - Subloop->getBlocksVector().end()); + Subloop->reverseBlock(1); std::reverse(Subloop->getSubLoopsVector().begin(), Subloop->getSubLoopsVector().end()); Subloop = Subloop->getParentLoop(); } for (; Subloop; Subloop = Subloop->getParentLoop()) - Subloop->getBlocksVector().push_back(Block); + Subloop->addBlockEntry(Block); } /// Analyze LoopInfo discovers loops during a postorder DominatorTree traversal diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index 5767c19..5926610 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -16,8 +16,8 @@ #define LLVM_ANALYSIS_LOOPPASS_H #include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/LegacyPassManagers.h" #include "llvm/Pass.h" -#include "llvm/PassManagers.h" #include <deque> namespace llvm { diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index 0d1ae8c..91224ad 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -64,6 +64,10 @@ bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); +/// \brief Tests if a value is a call or invoke to a library function that +/// allocates memory and never returns null (such as operator new). +bool isOperatorNewLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); //===----------------------------------------------------------------------===// // malloc Call Utility Functions. @@ -81,7 +85,7 @@ static inline CallInst *extractMallocCall(Value *I, /// isArrayMalloc - Returns the corresponding CallInst if the instruction /// is a call to malloc whose array size can be determined and the array size /// is not constant 1. Otherwise, return NULL. -const CallInst *isArrayMalloc(const Value *I, const DataLayout *TD, +const CallInst *isArrayMalloc(const Value *I, const DataLayout *DL, const TargetLibraryInfo *TLI); /// getMallocType - Returns the PointerType resulting from the malloc call. @@ -103,7 +107,7 @@ Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI); /// then return that multiple. For non-array mallocs, the multiple is /// constant 1. Otherwise, return NULL for mallocs whose array size cannot be /// determined. -Value *getMallocArraySize(CallInst *CI, const DataLayout *TD, +Value *getMallocArraySize(CallInst *CI, const DataLayout *DL, const TargetLibraryInfo *TLI, bool LookThroughSExt = false); @@ -143,7 +147,7 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { /// underlying object pointed to by Ptr. /// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, /// byval arguments, and global variables. -bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD, +bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *DL, const TargetLibraryInfo *TLI, bool RoundToAlign = false); @@ -155,7 +159,7 @@ typedef std::pair<APInt, APInt> SizeOffsetType; class ObjectSizeOffsetVisitor : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { - const DataLayout *TD; + const DataLayout *DL; const TargetLibraryInfo *TLI; bool RoundToAlign; unsigned IntTyBits; @@ -169,7 +173,7 @@ class ObjectSizeOffsetVisitor } public: - ObjectSizeOffsetVisitor(const DataLayout *TD, const TargetLibraryInfo *TLI, + ObjectSizeOffsetVisitor(const DataLayout *DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign = false); SizeOffsetType compute(Value *V); @@ -216,7 +220,7 @@ class ObjectSizeOffsetEvaluator typedef DenseMap<const Value*, WeakEvalType> CacheMapTy; typedef SmallPtrSet<const Value*, 8> PtrSetTy; - const DataLayout *TD; + const DataLayout *DL; const TargetLibraryInfo *TLI; LLVMContext &Context; BuilderTy Builder; @@ -224,6 +228,7 @@ class ObjectSizeOffsetEvaluator Value *Zero; CacheMapTy CacheMap; PtrSetTy SeenVals; + bool RoundToAlign; SizeOffsetEvalType unknown() { return std::make_pair((Value*)0, (Value*)0); @@ -231,8 +236,8 @@ class ObjectSizeOffsetEvaluator SizeOffsetEvalType compute_(Value *V); public: - ObjectSizeOffsetEvaluator(const DataLayout *TD, const TargetLibraryInfo *TLI, - LLVMContext &Context); + ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI, + LLVMContext &Context, bool RoundToAlign = false); SizeOffsetEvalType compute(Value *V); bool knownSize(SizeOffsetEvalType SizeOffset) { diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index ae11713..a5d098e 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -95,64 +95,6 @@ namespace llvm { //===--------------------------------------------------------------------===// // - // createProfileLoaderPass - This pass loads information from a profile dump - // file. - // - ModulePass *createProfileLoaderPass(); - extern char &ProfileLoaderPassID; - - //===--------------------------------------------------------------------===// - // - // createProfileMetadataLoaderPass - This pass loads information from a - // profile dump file and sets branch weight metadata. - // - ModulePass *createProfileMetadataLoaderPass(); - extern char &ProfileMetadataLoaderPassID; - - //===--------------------------------------------------------------------===// - // - // createNoProfileInfoPass - This pass implements the default "no profile". - // - ImmutablePass *createNoProfileInfoPass(); - - //===--------------------------------------------------------------------===// - // - // createProfileEstimatorPass - This pass estimates profiling information - // instead of loading it from a previous run. - // - FunctionPass *createProfileEstimatorPass(); - extern char &ProfileEstimatorPassID; - - //===--------------------------------------------------------------------===// - // - // createProfileVerifierPass - This pass verifies profiling information. - // - FunctionPass *createProfileVerifierPass(); - - //===--------------------------------------------------------------------===// - // - // createPathProfileLoaderPass - This pass loads information from a path - // profile dump file. - // - ModulePass *createPathProfileLoaderPass(); - extern char &PathProfileLoaderPassID; - - //===--------------------------------------------------------------------===// - // - // createNoPathProfileInfoPass - This pass implements the default - // "no path profile". - // - ImmutablePass *createNoPathProfileInfoPass(); - - //===--------------------------------------------------------------------===// - // - // createPathProfileVerifierPass - This pass verifies path profiling - // information. - // - ModulePass *createPathProfileVerifierPass(); - - //===--------------------------------------------------------------------===// - // // createDSAAPass - This pass implements simple context sensitive alias // analysis. // @@ -194,6 +136,13 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createDelinearizationPass - This pass implements attempts to restore + // multidimensional array indices from linearized expressions. + // + FunctionPass *createDelinearizationPass(); + + //===--------------------------------------------------------------------===// + // // Minor pass prototypes, allowing us to expose them through bugpoint and // analyze. FunctionPass *createInstCountPass(); diff --git a/include/llvm/Analysis/PathNumbering.h b/include/llvm/Analysis/PathNumbering.h deleted file mode 100644 index 400a37d..0000000 --- a/include/llvm/Analysis/PathNumbering.h +++ /dev/null @@ -1,304 +0,0 @@ -//===- PathNumbering.h ----------------------------------------*- C++ -*---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Ball-Larus path numbers uniquely identify paths through a directed acyclic -// graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony -// edges to obtain a DAG, and thus the unique path numbers [Ball96]. -// -// The purpose of this analysis is to enumerate the edges in a CFG in order -// to obtain paths from path numbers in a convenient manner. As described in -// [Ball96] edges can be enumerated such that given a path number by following -// the CFG and updating the path number, the path is obtained. -// -// [Ball96] -// T. Ball and J. R. Larus. "Efficient Path Profiling." -// International Symposium on Microarchitecture, pages 46-57, 1996. -// http://portal.acm.org/citation.cfm?id=243857 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PATHNUMBERING_H -#define LLVM_ANALYSIS_PATHNUMBERING_H - -#include "llvm/Analysis/ProfileInfoTypes.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Pass.h" -#include "llvm/Support/CFG.h" -#include <map> -#include <stack> -#include <vector> - -namespace llvm { -class BallLarusNode; -class BallLarusEdge; -class BallLarusDag; - -// typedefs for storage/ interators of various DAG components -typedef std::vector<BallLarusNode*> BLNodeVector; -typedef std::vector<BallLarusNode*>::iterator BLNodeIterator; -typedef std::vector<BallLarusEdge*> BLEdgeVector; -typedef std::vector<BallLarusEdge*>::iterator BLEdgeIterator; -typedef std::map<BasicBlock*, BallLarusNode*> BLBlockNodeMap; -typedef std::stack<BallLarusNode*> BLNodeStack; - -// Represents a basic block with information necessary for the BallLarus -// algorithms. -class BallLarusNode { -public: - enum NodeColor { WHITE, GRAY, BLACK }; - - // Constructor: Initializes a new Node for the given BasicBlock - BallLarusNode(BasicBlock* BB) : - _basicBlock(BB), _numberPaths(0), _color(WHITE) { - static unsigned nextUID = 0; - _uid = nextUID++; - } - - // Returns the basic block for the BallLarusNode - BasicBlock* getBlock(); - - // Get/set the number of paths to the exit starting at the node. - unsigned getNumberPaths(); - void setNumberPaths(unsigned numberPaths); - - // Get/set the NodeColor used in graph algorithms. - NodeColor getColor(); - void setColor(NodeColor color); - - // Iterator information for predecessor edges. Includes phony and - // backedges. - BLEdgeIterator predBegin(); - BLEdgeIterator predEnd(); - unsigned getNumberPredEdges(); - - // Iterator information for successor edges. Includes phony and - // backedges. - BLEdgeIterator succBegin(); - BLEdgeIterator succEnd(); - unsigned getNumberSuccEdges(); - - // Add an edge to the predecessor list. - void addPredEdge(BallLarusEdge* edge); - - // Remove an edge from the predecessor list. - void removePredEdge(BallLarusEdge* edge); - - // Add an edge to the successor list. - void addSuccEdge(BallLarusEdge* edge); - - // Remove an edge from the successor list. - void removeSuccEdge(BallLarusEdge* edge); - - // Returns the name of the BasicBlock being represented. If BasicBlock - // is null then returns "<null>". If BasicBlock has no name, then - // "<unnamed>" is returned. Intended for use with debug output. - std::string getName(); - -private: - // The corresponding underlying BB. - BasicBlock* _basicBlock; - - // Holds the predecessor edges of this node. - BLEdgeVector _predEdges; - - // Holds the successor edges of this node. - BLEdgeVector _succEdges; - - // The number of paths from the node to the exit. - unsigned _numberPaths; - - // 'Color' used by graph algorithms to mark the node. - NodeColor _color; - - // Unique ID to ensure naming difference with dotgraphs - unsigned _uid; - - // Removes an edge from an edgeVector. Used by removePredEdge and - // removeSuccEdge. - void removeEdge(BLEdgeVector& v, BallLarusEdge* e); -}; - -// Represents an edge in the Dag. For an edge, v -> w, v is the source, and -// w is the target. -class BallLarusEdge { -public: - enum EdgeType { NORMAL, BACKEDGE, SPLITEDGE, - BACKEDGE_PHONY, SPLITEDGE_PHONY, CALLEDGE_PHONY }; - - // Constructor: Initializes an BallLarusEdge with a source and target. - BallLarusEdge(BallLarusNode* source, BallLarusNode* target, - unsigned duplicateNumber) - : _source(source), _target(target), _weight(0), _edgeType(NORMAL), - _realEdge(NULL), _duplicateNumber(duplicateNumber) {} - - // Returns the source/ target node of this edge. - BallLarusNode* getSource() const; - BallLarusNode* getTarget() const; - - // Sets the type of the edge. - EdgeType getType() const; - - // Gets the type of the edge. - void setType(EdgeType type); - - // Returns the weight of this edge. Used to decode path numbers to - // sequences of basic blocks. - unsigned getWeight(); - - // Sets the weight of the edge. Used during path numbering. - void setWeight(unsigned weight); - - // Gets/sets the phony edge originating at the root. - BallLarusEdge* getPhonyRoot(); - void setPhonyRoot(BallLarusEdge* phonyRoot); - - // Gets/sets the phony edge terminating at the exit. - BallLarusEdge* getPhonyExit(); - void setPhonyExit(BallLarusEdge* phonyExit); - - // Gets/sets the associated real edge if this is a phony edge. - BallLarusEdge* getRealEdge(); - void setRealEdge(BallLarusEdge* realEdge); - - // Returns the duplicate number of the edge. - unsigned getDuplicateNumber(); - -protected: - // Source node for this edge. - BallLarusNode* _source; - - // Target node for this edge. - BallLarusNode* _target; - -private: - // Edge weight cooresponding to path number increments before removing - // increments along a spanning tree. The sum over the edge weights gives - // the path number. - unsigned _weight; - - // Type to represent for what this edge is intended - EdgeType _edgeType; - - // For backedges and split-edges, the phony edge which is linked to the - // root node of the DAG. This contains a path number initialization. - BallLarusEdge* _phonyRoot; - - // For backedges and split-edges, the phony edge which is linked to the - // exit node of the DAG. This contains a path counter increment, and - // potentially a path number increment. - BallLarusEdge* _phonyExit; - - // If this is a phony edge, _realEdge is a link to the back or split - // edge. Otherwise, this is null. - BallLarusEdge* _realEdge; - - // An ID to differentiate between those edges which have the same source - // and destination blocks. - unsigned _duplicateNumber; -}; - -// Represents the Ball Larus DAG for a given Function. Can calculate -// various properties required for instrumentation or analysis. E.g. the -// edge weights that determine the path number. -class BallLarusDag { -public: - // Initializes a BallLarusDag from the CFG of a given function. Must - // call init() after creation, since some initialization requires - // virtual functions. - BallLarusDag(Function &F) - : _root(NULL), _exit(NULL), _function(F) {} - - // Initialization that requires virtual functions which are not fully - // functional in the constructor. - void init(); - - // Frees all memory associated with the DAG. - virtual ~BallLarusDag(); - - // Calculate the path numbers by assigning edge increments as prescribed - // in Ball-Larus path profiling. - void calculatePathNumbers(); - - // Returns the number of paths for the DAG. - unsigned getNumberOfPaths(); - - // Returns the root (i.e. entry) node for the DAG. - BallLarusNode* getRoot(); - - // Returns the exit node for the DAG. - BallLarusNode* getExit(); - - // Returns the function for the DAG. - Function& getFunction(); - - // Clears the node colors. - void clearColors(BallLarusNode::NodeColor color); - -protected: - // All nodes in the DAG. - BLNodeVector _nodes; - - // All edges in the DAG. - BLEdgeVector _edges; - - // All backedges in the DAG. - BLEdgeVector _backEdges; - - // Allows subclasses to determine which type of Node is created. - // Override this method to produce subclasses of BallLarusNode if - // necessary. The destructor of BallLarusDag will call free on each pointer - // created. - virtual BallLarusNode* createNode(BasicBlock* BB); - - // Allows subclasses to determine which type of Edge is created. - // Override this method to produce subclasses of BallLarusEdge if - // necessary. Parameters source and target will have been created by - // createNode and can be cast to the subclass of BallLarusNode* - // returned by createNode. The destructor of BallLarusDag will call free - // on each pointer created. - virtual BallLarusEdge* createEdge(BallLarusNode* source, BallLarusNode* - target, unsigned duplicateNumber); - - // Proxy to node's constructor. Updates the DAG state. - BallLarusNode* addNode(BasicBlock* BB); - - // Proxy to edge's constructor. Updates the DAG state. - BallLarusEdge* addEdge(BallLarusNode* source, BallLarusNode* target, - unsigned duplicateNumber); - -private: - // The root (i.e. entry) node for this DAG. - BallLarusNode* _root; - - // The exit node for this DAG. - BallLarusNode* _exit; - - // The function represented by this DAG. - Function& _function; - - // Processes one node and its imediate edges for building the DAG. - void buildNode(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack); - - // Process an edge in the CFG for DAG building. - void buildEdge(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack, - BallLarusNode* currentNode, BasicBlock* succBB, - unsigned duplicateNumber); - - // The weight on each edge is the increment required along any path that - // contains that edge. - void calculatePathNumbersFrom(BallLarusNode* node); - - // Adds a backedge with its phony edges. Updates the DAG state. - void addBackedge(BallLarusNode* source, BallLarusNode* target, - unsigned duplicateCount); -}; -} // end namespace llvm - -#endif diff --git a/include/llvm/Analysis/PathProfileInfo.h b/include/llvm/Analysis/PathProfileInfo.h deleted file mode 100644 index 4fce16e..0000000 --- a/include/llvm/Analysis/PathProfileInfo.h +++ /dev/null @@ -1,112 +0,0 @@ -//===- PathProfileInfo.h --------------------------------------*- C++ -*---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file outlines the interface used by optimizers to load path profiles. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PATHPROFILEINFO_H -#define LLVM_ANALYSIS_PATHPROFILEINFO_H - -#include "llvm/Analysis/PathNumbering.h" -#include "llvm/IR/BasicBlock.h" - -namespace llvm { - -class ProfilePath; -class ProfilePathEdge; -class PathProfileInfo; - -typedef std::vector<ProfilePathEdge> ProfilePathEdgeVector; -typedef std::vector<ProfilePathEdge>::iterator ProfilePathEdgeIterator; - -typedef std::vector<BasicBlock*> ProfilePathBlockVector; -typedef std::vector<BasicBlock*>::iterator ProfilePathBlockIterator; - -typedef std::map<unsigned int,ProfilePath*> ProfilePathMap; -typedef std::map<unsigned int,ProfilePath*>::iterator ProfilePathIterator; - -typedef std::map<Function*,unsigned int> FunctionPathCountMap; -typedef std::map<Function*,ProfilePathMap> FunctionPathMap; -typedef std::map<Function*,ProfilePathMap>::iterator FunctionPathIterator; - -class ProfilePathEdge { -public: - ProfilePathEdge(BasicBlock* source, BasicBlock* target, - unsigned duplicateNumber); - - inline unsigned getDuplicateNumber() { return _duplicateNumber; } - inline BasicBlock* getSource() { return _source; } - inline BasicBlock* getTarget() { return _target; } - -protected: - BasicBlock* _source; - BasicBlock* _target; - unsigned _duplicateNumber; -}; - -class ProfilePath { -public: - ProfilePath(unsigned int number, unsigned int count, - double countStdDev, PathProfileInfo* ppi); - - double getFrequency() const; - - inline unsigned int getNumber() const { return _number; } - inline unsigned int getCount() const { return _count; } - inline double getCountStdDev() const { return _countStdDev; } - - ProfilePathEdgeVector* getPathEdges() const; - ProfilePathBlockVector* getPathBlocks() const; - - BasicBlock* getFirstBlockInPath() const; - -private: - unsigned int _number; - unsigned int _count; - double _countStdDev; - - // double pointer back to the profiling info - PathProfileInfo* _ppi; -}; - -// TODO: overload [] operator for getting path -// Add: getFunctionCallCount() -class PathProfileInfo { - public: - PathProfileInfo(); - ~PathProfileInfo(); - - void setCurrentFunction(Function* F); - Function* getCurrentFunction() const; - BasicBlock* getCurrentFunctionEntry(); - - ProfilePath* getPath(unsigned int number); - unsigned int getPotentialPathCount(); - - ProfilePathIterator pathBegin(); - ProfilePathIterator pathEnd(); - unsigned int pathsRun(); - - static char ID; // Pass identification - std::string argList; - -protected: - FunctionPathMap _functionPaths; - FunctionPathCountMap _functionPathCounts; - -private: - BallLarusDag* _currentDag; - Function* _currentFunction; - - friend class ProfilePath; -}; -} // end namespace llvm - -#endif diff --git a/include/llvm/Analysis/ProfileDataLoader.h b/include/llvm/Analysis/ProfileDataLoader.h deleted file mode 100644 index 90097f7..0000000 --- a/include/llvm/Analysis/ProfileDataLoader.h +++ /dev/null @@ -1,140 +0,0 @@ -//===- ProfileDataLoader.h - Load & convert profile info ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The ProfileDataLoader class is used to load profiling data from a dump file. -// The ProfileDataT<FType, BType> class is used to store the mapping of this -// data to control flow edges. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PROFILEDATALOADER_H -#define LLVM_ANALYSIS_PROFILEDATALOADER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include <string> - -namespace llvm { - -class ModulePass; -class Function; -class BasicBlock; - -// Helper for dumping edges to dbgs(). -raw_ostream& operator<<(raw_ostream &O, std::pair<const BasicBlock *, - const BasicBlock *> E); - -/// \brief The ProfileDataT<FType, BType> class is used to store the mapping of -/// profiling data to control flow edges. -/// -/// An edge is defined by its source and sink basic blocks. -template<class FType, class BType> -class ProfileDataT { -public: - // The profiling information defines an Edge by its source and sink basic - // blocks. - typedef std::pair<const BType*, const BType*> Edge; - -private: - typedef DenseMap<Edge, unsigned> EdgeWeights; - - /// \brief Count the number of times a transition between two blocks is - /// executed. - /// - /// As a special case, we also hold an edge from the null BasicBlock to the - /// entry block to indicate how many times the function was entered. - DenseMap<const FType*, EdgeWeights> EdgeInformation; - -public: - /// getFunction() - Returns the Function for an Edge. - static const FType *getFunction(Edge e) { - // e.first may be NULL - assert(((!e.first) || (e.first->getParent() == e.second->getParent())) - && "A ProfileData::Edge can not be between two functions"); - assert(e.second && "A ProfileData::Edge must have a real sink"); - return e.second->getParent(); - } - - /// getEdge() - Creates an Edge between two BasicBlocks. - static Edge getEdge(const BType *Src, const BType *Dest) { - return Edge(Src, Dest); - } - - /// getEdgeWeight - Return the number of times that a given edge was - /// executed. - unsigned getEdgeWeight(Edge e) const { - const FType *f = getFunction(e); - assert((EdgeInformation.find(f) != EdgeInformation.end()) - && "No profiling information for function"); - EdgeWeights weights = EdgeInformation.find(f)->second; - - assert((weights.find(e) != weights.end()) - && "No profiling information for edge"); - return weights.find(e)->second; - } - - /// addEdgeWeight - Add 'weight' to the already stored execution count for - /// this edge. - void addEdgeWeight(Edge e, unsigned weight) { - EdgeInformation[getFunction(e)][e] += weight; - } -}; - -typedef ProfileDataT<Function, BasicBlock> ProfileData; -//typedef ProfileDataT<MachineFunction, MachineBasicBlock> MachineProfileData; - -/// The ProfileDataLoader class is used to load raw profiling data from the -/// dump file. -class ProfileDataLoader { -private: - /// The name of the file where the raw profiling data is stored. - const std::string &Filename; - - /// A vector of the command line arguments used when the target program was - /// run to generate profiling data. One entry per program run. - SmallVector<std::string, 1> CommandLines; - - /// The raw values for how many times each edge was traversed, values from - /// multiple program runs are accumulated. - SmallVector<unsigned, 32> EdgeCounts; - -public: - /// ProfileDataLoader ctor - Read the specified profiling data file, exiting - /// the program if the file is invalid or broken. - ProfileDataLoader(const char *ToolName, const std::string &Filename); - - /// A special value used to represent the weight of an edge which has not - /// been counted yet. - static const unsigned Uncounted; - - /// getNumExecutions - Return the number of times the target program was run - /// to generate this profiling data. - unsigned getNumExecutions() const { return CommandLines.size(); } - - /// getExecution - Return the command line parameters used to generate the - /// i'th set of profiling data. - const std::string &getExecution(unsigned i) const { return CommandLines[i]; } - - const std::string &getFileName() const { return Filename; } - - /// getRawEdgeCounts - Return the raw profiling data, this is just a list of - /// numbers with no mappings to edges. - ArrayRef<unsigned> getRawEdgeCounts() const { return EdgeCounts; } -}; - -/// createProfileMetadataLoaderPass - This function returns a Pass that loads -/// the profiling information for the module from the specified filename. -ModulePass *createProfileMetadataLoaderPass(const std::string &Filename); - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/ProfileDataTypes.h b/include/llvm/Analysis/ProfileDataTypes.h deleted file mode 100644 index 1be15e0..0000000 --- a/include/llvm/Analysis/ProfileDataTypes.h +++ /dev/null @@ -1,39 +0,0 @@ -/*===-- ProfileDataTypes.h - Profiling info shared constants --------------===*\ -|* -|* The LLVM Compiler Infrastructure -|* -|* This file is distributed under the University of Illinois Open Source -|* License. See LICENSE.TXT for details. -|* -|*===----------------------------------------------------------------------===*| -|* -|* This file defines constants shared by the various different profiling -|* runtime libraries and the LLVM C++ profile metadata loader. It must be a -|* C header because, at present, the profiling runtimes are written in C. -|* -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_ANALYSIS_PROFILEDATATYPES_H -#define LLVM_ANALYSIS_PROFILEDATATYPES_H - -/* Included by libprofile. */ -#if defined(__cplusplus) -extern "C" { -#endif - -/* TODO: Strip out unused entries once ProfileInfo etc has been removed. */ -enum ProfilingType { - ArgumentInfo = 1, /* The command line argument block */ - FunctionInfo = 2, /* Function profiling information */ - BlockInfo = 3, /* Block profiling information */ - EdgeInfo = 4, /* Edge profiling information */ - PathInfo = 5, /* Path profiling information */ - BBTraceInfo = 6, /* Basic block trace information */ - OptEdgeInfo = 7 /* Edge profiling information, optimal version */ -}; - -#if defined(__cplusplus) -} -#endif - -#endif /* LLVM_ANALYSIS_PROFILEDATATYPES_H */ diff --git a/include/llvm/Analysis/ProfileInfo.h b/include/llvm/Analysis/ProfileInfo.h deleted file mode 100644 index 5d17fa1..0000000 --- a/include/llvm/Analysis/ProfileInfo.h +++ /dev/null @@ -1,247 +0,0 @@ -//===- llvm/Analysis/ProfileInfo.h - Profile Info Interface -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the generic ProfileInfo interface, which is used as the -// common interface used by all clients of profiling information, and -// implemented either by making static guestimations, or by actually reading in -// profiling information gathered by running the program. -// -// Note that to be useful, all profile-based optimizations should preserve -// ProfileInfo, which requires that they notify it when changes to the CFG are -// made. (This is not implemented yet.) -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PROFILEINFO_H -#define LLVM_ANALYSIS_PROFILEINFO_H - -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <map> -#include <set> -#include <string> - -namespace llvm { - class Pass; - class raw_ostream; - - class BasicBlock; - class Function; - class MachineBasicBlock; - class MachineFunction; - - // Helper for dumping edges to dbgs(). - raw_ostream& operator<<(raw_ostream &O, std::pair<const BasicBlock *, const BasicBlock *> E); - raw_ostream& operator<<(raw_ostream &O, std::pair<const MachineBasicBlock *, const MachineBasicBlock *> E); - - raw_ostream& operator<<(raw_ostream &O, const BasicBlock *BB); - raw_ostream& operator<<(raw_ostream &O, const MachineBasicBlock *MBB); - - raw_ostream& operator<<(raw_ostream &O, const Function *F); - raw_ostream& operator<<(raw_ostream &O, const MachineFunction *MF); - - /// ProfileInfo Class - This class holds and maintains profiling - /// information for some unit of code. - template<class FType, class BType> - class ProfileInfoT { - public: - // Types for handling profiling information. - typedef std::pair<const BType*, const BType*> Edge; - typedef std::pair<Edge, double> EdgeWeight; - typedef std::map<Edge, double> EdgeWeights; - typedef std::map<const BType*, double> BlockCounts; - typedef std::map<const BType*, const BType*> Path; - - protected: - // EdgeInformation - Count the number of times a transition between two - // blocks is executed. As a special case, we also hold an edge from the - // null BasicBlock to the entry block to indicate how many times the - // function was entered. - std::map<const FType*, EdgeWeights> EdgeInformation; - - // BlockInformation - Count the number of times a block is executed. - std::map<const FType*, BlockCounts> BlockInformation; - - // FunctionInformation - Count the number of times a function is executed. - std::map<const FType*, double> FunctionInformation; - - ProfileInfoT<MachineFunction, MachineBasicBlock> *MachineProfile; - public: - static char ID; // Class identification, replacement for typeinfo - ProfileInfoT(); - ~ProfileInfoT(); // We want to be subclassed - - // MissingValue - The value that is returned for execution counts in case - // no value is available. - static const double MissingValue; - - // getFunction() - Returns the Function for an Edge, checking for validity. - static const FType* getFunction(Edge e) { - if (e.first) - return e.first->getParent(); - if (e.second) - return e.second->getParent(); - llvm_unreachable("Invalid ProfileInfo::Edge"); - } - - // getEdge() - Creates an Edge from two BasicBlocks. - static Edge getEdge(const BType *Src, const BType *Dest) { - return std::make_pair(Src, Dest); - } - - //===------------------------------------------------------------------===// - /// Profile Information Queries - /// - double getExecutionCount(const FType *F); - - double getExecutionCount(const BType *BB); - - void setExecutionCount(const BType *BB, double w); - - void addExecutionCount(const BType *BB, double w); - - double getEdgeWeight(Edge e) const { - typename std::map<const FType*, EdgeWeights>::const_iterator J = - EdgeInformation.find(getFunction(e)); - if (J == EdgeInformation.end()) return MissingValue; - - typename EdgeWeights::const_iterator I = J->second.find(e); - if (I == J->second.end()) return MissingValue; - - return I->second; - } - - void setEdgeWeight(Edge e, double w) { - DEBUG_WITH_TYPE("profile-info", - dbgs() << "Creating Edge " << e - << " (weight: " << format("%.20g",w) << ")\n"); - EdgeInformation[getFunction(e)][e] = w; - } - - void addEdgeWeight(Edge e, double w); - - EdgeWeights &getEdgeWeights (const FType *F) { - return EdgeInformation[F]; - } - - //===------------------------------------------------------------------===// - /// Analysis Update Methods - /// - void removeBlock(const BType *BB); - - void removeEdge(Edge e); - - void replaceEdge(const Edge &, const Edge &); - - enum GetPathMode { - GetPathToExit = 1, - GetPathToValue = 2, - GetPathToDest = 4, - GetPathWithNewEdges = 8 - }; - - const BType *GetPath(const BType *Src, const BType *Dest, - Path &P, unsigned Mode); - - void divertFlow(const Edge &, const Edge &); - - void splitEdge(const BType *FirstBB, const BType *SecondBB, - const BType *NewBB, bool MergeIdenticalEdges = false); - - void splitBlock(const BType *Old, const BType* New); - - void splitBlock(const BType *BB, const BType* NewBB, - BType *const *Preds, unsigned NumPreds); - - void replaceAllUses(const BType *RmBB, const BType *DestBB); - - void transfer(const FType *Old, const FType *New); - - void repair(const FType *F); - - void dump(FType *F = 0, bool real = true) { - dbgs() << "**** This is ProfileInfo " << this << " speaking:\n"; - if (!real) { - typename std::set<const FType*> Functions; - - dbgs() << "Functions: \n"; - if (F) { - dbgs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n"; - Functions.insert(F); - } else { - for (typename std::map<const FType*, double>::iterator fi = FunctionInformation.begin(), - fe = FunctionInformation.end(); fi != fe; ++fi) { - dbgs() << fi->first << "@" << format("%p",fi->first) << ": " << format("%.20g",fi->second) << "\n"; - Functions.insert(fi->first); - } - } - - for (typename std::set<const FType*>::iterator FI = Functions.begin(), FE = Functions.end(); - FI != FE; ++FI) { - const FType *F = *FI; - typename std::map<const FType*, BlockCounts>::iterator bwi = BlockInformation.find(F); - dbgs() << "BasicBlocks for Function " << F << ":\n"; - for (typename BlockCounts::const_iterator bi = bwi->second.begin(), be = bwi->second.end(); bi != be; ++bi) { - dbgs() << bi->first << "@" << format("%p", bi->first) << ": " << format("%.20g",bi->second) << "\n"; - } - } - - for (typename std::set<const FType*>::iterator FI = Functions.begin(), FE = Functions.end(); - FI != FE; ++FI) { - typename std::map<const FType*, EdgeWeights>::iterator ei = EdgeInformation.find(*FI); - dbgs() << "Edges for Function " << ei->first << ":\n"; - for (typename EdgeWeights::iterator ewi = ei->second.begin(), ewe = ei->second.end(); - ewi != ewe; ++ewi) { - dbgs() << ewi->first << ": " << format("%.20g",ewi->second) << "\n"; - } - } - } else { - assert(F && "No function given, this is not supported!"); - dbgs() << "Functions: \n"; - dbgs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n"; - - dbgs() << "BasicBlocks for Function " << F << ":\n"; - for (typename FType::const_iterator BI = F->begin(), BE = F->end(); - BI != BE; ++BI) { - const BType *BB = &(*BI); - dbgs() << BB << "@" << format("%p", BB) << ": " << format("%.20g",getExecutionCount(BB)) << "\n"; - } - } - dbgs() << "**** ProfileInfo " << this << ", over and out.\n"; - } - - bool CalculateMissingEdge(const BType *BB, Edge &removed, bool assumeEmptyExit = false); - - bool EstimateMissingEdges(const BType *BB); - - ProfileInfoT<MachineFunction, MachineBasicBlock> *MI() { - if (MachineProfile == 0) - MachineProfile = new ProfileInfoT<MachineFunction, MachineBasicBlock>(); - return MachineProfile; - } - - bool hasMI() const { - return (MachineProfile != 0); - } - }; - - typedef ProfileInfoT<Function, BasicBlock> ProfileInfo; - typedef ProfileInfoT<MachineFunction, MachineBasicBlock> MachineProfileInfo; - - /// createProfileLoaderPass - This function returns a Pass that loads the - /// profiling information for the module from the specified filename, making - /// it available to the optimizers. - Pass *createProfileLoaderPass(const std::string &Filename); - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/ProfileInfoLoader.h b/include/llvm/Analysis/ProfileInfoLoader.h deleted file mode 100644 index e0f49f3..0000000 --- a/include/llvm/Analysis/ProfileInfoLoader.h +++ /dev/null @@ -1,81 +0,0 @@ -//===- ProfileInfoLoader.h - Load & convert profile information -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The ProfileInfoLoader class is used to load and represent profiling -// information read in from the dump file. If conversions between formats are -// needed, it can also do this. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PROFILEINFOLOADER_H -#define LLVM_ANALYSIS_PROFILEINFOLOADER_H - -#include <string> -#include <utility> -#include <vector> - -namespace llvm { - -class Module; -class Function; -class BasicBlock; - -class ProfileInfoLoader { - const std::string &Filename; - std::vector<std::string> CommandLines; - std::vector<unsigned> FunctionCounts; - std::vector<unsigned> BlockCounts; - std::vector<unsigned> EdgeCounts; - std::vector<unsigned> OptimalEdgeCounts; - std::vector<unsigned> BBTrace; -public: - // ProfileInfoLoader ctor - Read the specified profiling data file, exiting - // the program if the file is invalid or broken. - ProfileInfoLoader(const char *ToolName, const std::string &Filename); - - static const unsigned Uncounted; - - unsigned getNumExecutions() const { return CommandLines.size(); } - const std::string &getExecution(unsigned i) const { return CommandLines[i]; } - - const std::string &getFileName() const { return Filename; } - - // getRawFunctionCounts - This method is used by consumers of function - // counting information. - // - const std::vector<unsigned> &getRawFunctionCounts() const { - return FunctionCounts; - } - - // getRawBlockCounts - This method is used by consumers of block counting - // information. - // - const std::vector<unsigned> &getRawBlockCounts() const { - return BlockCounts; - } - - // getEdgeCounts - This method is used by consumers of edge counting - // information. - // - const std::vector<unsigned> &getRawEdgeCounts() const { - return EdgeCounts; - } - - // getEdgeOptimalCounts - This method is used by consumers of optimal edge - // counting information. - // - const std::vector<unsigned> &getRawOptimalEdgeCounts() const { - return OptimalEdgeCounts; - } - -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/ProfileInfoTypes.h b/include/llvm/Analysis/ProfileInfoTypes.h deleted file mode 100644 index 45aab5b..0000000 --- a/include/llvm/Analysis/ProfileInfoTypes.h +++ /dev/null @@ -1,52 +0,0 @@ -/*===-- ProfileInfoTypes.h - Profiling info shared constants --------------===*\ -|* -|* The LLVM Compiler Infrastructure -|* -|* This file is distributed under the University of Illinois Open Source -|* License. See LICENSE.TXT for details. -|* -|*===----------------------------------------------------------------------===*| -|* -|* This file defines constants shared by the various different profiling -|* runtime libraries and the LLVM C++ profile info loader. It must be a -|* C header because, at present, the profiling runtimes are written in C. -|* -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H -#define LLVM_ANALYSIS_PROFILEINFOTYPES_H - -/* Included by libprofile. */ -#if defined(__cplusplus) -extern "C" { -#endif - -/* IDs to distinguish between those path counters stored in hashses vs arrays */ -enum ProfilingStorageType { - ProfilingArray = 1, - ProfilingHash = 2 -}; - -#include "llvm/Analysis/ProfileDataTypes.h" - -/* - * The header for tables that map path numbers to path counters. - */ -typedef struct { - unsigned fnNumber; /* function number for these counters */ - unsigned numEntries; /* number of entries stored */ -} PathProfileHeader; - -/* - * Describes an entry in a tagged table for path counters. - */ -typedef struct { - unsigned pathNumber; - unsigned pathCounter; -} PathProfileTableEntry; - -#if defined(__cplusplus) -} -#endif - -#endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */ diff --git a/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h index 6ae3191..3907ad9 100644 --- a/include/llvm/Analysis/RegionPass.h +++ b/include/llvm/Analysis/RegionPass.h @@ -18,8 +18,8 @@ #include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/Function.h" +#include "llvm/IR/LegacyPassManagers.h" #include "llvm/Pass.h" -#include "llvm/PassManagers.h" #include <deque> namespace llvm { diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 3817e41..d7f6178 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -189,15 +189,16 @@ namespace llvm { /// Convenient NoWrapFlags manipulation that hides enum casts and is /// visible in the ScalarEvolution name space. - static SCEV::NoWrapFlags maskFlags(SCEV::NoWrapFlags Flags, int Mask) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + maskFlags(SCEV::NoWrapFlags Flags, int Mask) { return (SCEV::NoWrapFlags)(Flags & Mask); } - static SCEV::NoWrapFlags setFlags(SCEV::NoWrapFlags Flags, - SCEV::NoWrapFlags OnFlags) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + setFlags(SCEV::NoWrapFlags Flags, SCEV::NoWrapFlags OnFlags) { return (SCEV::NoWrapFlags)(Flags | OnFlags); } - static SCEV::NoWrapFlags clearFlags(SCEV::NoWrapFlags Flags, - SCEV::NoWrapFlags OffFlags) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + clearFlags(SCEV::NoWrapFlags Flags, SCEV::NoWrapFlags OffFlags) { return (SCEV::NoWrapFlags)(Flags & ~OffFlags); } @@ -361,18 +362,18 @@ namespace llvm { /// that we attempt to compute getSCEVAtScope information for, which can /// be expensive in extreme cases. DenseMap<const SCEV *, - std::map<const Loop *, const SCEV *> > ValuesAtScopes; + SmallVector<std::pair<const Loop *, const SCEV *>, 2> > ValuesAtScopes; /// LoopDispositions - Memoized computeLoopDisposition results. DenseMap<const SCEV *, - std::map<const Loop *, LoopDisposition> > LoopDispositions; + SmallVector<std::pair<const Loop *, LoopDisposition>, 2> > LoopDispositions; /// computeLoopDisposition - Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); /// BlockDispositions - Memoized computeBlockDisposition results. DenseMap<const SCEV *, - std::map<const BasicBlock *, BlockDisposition> > BlockDispositions; + SmallVector<std::pair<const BasicBlock *, BlockDisposition>, 2> > BlockDispositions; /// computeBlockDisposition - Compute a BlockDisposition value. BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); @@ -426,14 +427,6 @@ namespace llvm { /// resolution. void ForgetSymbolicName(Instruction *I, const SCEV *SymName); - /// getBECount - Subtract the end and start values and divide by the step, - /// rounding up, to get the number of times the backedge is executed. Return - /// CouldNotCompute if an intermediate computation overflows. - const SCEV *getBECount(const SCEV *Start, - const SCEV *End, - const SCEV *Step, - bool NoWrap); - /// getBackedgeTakenInfo - Return the BackedgeTakenInfo for the given /// loop, lazily computing new values if the loop hasn't been analyzed /// yet. @@ -498,6 +491,8 @@ namespace llvm { /// less-than is signed. ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L, bool isSigned, bool IsSubExpr); + ExitLimit HowManyGreaterThans(const SCEV *LHS, const SCEV *RHS, + const Loop *L, bool isSigned, bool IsSubExpr); /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB /// (which may not be an immediate predecessor) which has exactly one @@ -636,21 +631,15 @@ namespace llvm { const SCEV *getUnknown(Value *V); const SCEV *getCouldNotCompute(); - /// getSizeOfExpr - Return an expression for sizeof on the given type. - /// - const SCEV *getSizeOfExpr(Type *AllocTy); - - /// getAlignOfExpr - Return an expression for alignof on the given type. + /// getSizeOfExpr - Return an expression for sizeof AllocTy that is type + /// IntTy /// - const SCEV *getAlignOfExpr(Type *AllocTy); + const SCEV *getSizeOfExpr(Type *IntTy, Type *AllocTy); - /// getOffsetOfExpr - Return an expression for offsetof on the given field. + /// getOffsetOfExpr - Return an expression for offsetof on the given field + /// with type IntTy /// - const SCEV *getOffsetOfExpr(StructType *STy, unsigned FieldNo); - - /// getOffsetOfExpr - Return an expression for offsetof on the given field. - /// - const SCEV *getOffsetOfExpr(Type *CTy, Constant *FieldNo); + const SCEV *getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo); /// getNegativeSCEV - Return the SCEV object corresponding to -V. /// @@ -886,6 +875,24 @@ namespace llvm { virtual void verifyAnalysis() const; private: + /// Compute the backedge taken count knowing the interval difference, the + /// stride and presence of the equality in the comparison. + const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride, + bool Equality); + + /// Verify if an linear IV with positive stride can overflow when in a + /// less-than comparison, knowing the invariant term of the comparison, + /// the stride and the knowledge of NSW/NUW flags on the recurrence. + bool doesIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride, + bool IsSigned, bool NoWrap); + + /// Verify if an linear IV with negative stride can overflow when in a + /// greater-than comparison, knowing the invariant term of the comparison, + /// the stride and the knowledge of NSW/NUW flags on the recurrence. + bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, + bool IsSigned, bool NoWrap); + + private: FoldingSet<SCEV> UniqueSCEVs; BumpPtrAllocator SCEVAllocator; diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 00779fc..4433be0 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -26,7 +26,7 @@ namespace llvm { /// Return true if the given expression is safe to expand in the sense that /// all materialized values are safe to speculate. - bool isSafeToExpand(const SCEV *S); + bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE); /// SCEVExpander - This class uses information about analyze scalars to /// rewrite expressions in canonical form. @@ -252,8 +252,6 @@ namespace llvm { void rememberInstruction(Value *I); - void restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I); - bool isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L); bool isExpandedAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L); diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index eac9113..9cd902a 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -351,8 +351,14 @@ namespace llvm { static inline bool classof(const SCEV *S) { return S->getSCEVType() == scAddRecExpr; } - }; + /// Splits the SCEV into two vectors of SCEVs representing the subscripts + /// and sizes of an array access. Returns the remainder of the + /// delinearization that is the offset start of the array. + const SCEV *delinearize(ScalarEvolution &SE, + SmallVectorImpl<const SCEV *> &Subscripts, + SmallVectorImpl<const SCEV *> &Sizes) const; + }; //===--------------------------------------------------------------------===// /// SCEVSMaxExpr - This class represents a signed maximum selection. @@ -549,53 +555,60 @@ namespace llvm { T.visitAll(Root); } - /// The SCEVRewriter takes a scalar evolution expression and copies all its - /// components. The result after a rewrite is an identical SCEV. - struct SCEVRewriter - : public SCEVVisitor<SCEVRewriter, const SCEV*> { + typedef DenseMap<const Value*, Value*> ValueToValueMap; + + /// The SCEVParameterRewriter takes a scalar evolution expression and updates + /// the SCEVUnknown components following the Map (Value -> Value). + struct SCEVParameterRewriter + : public SCEVVisitor<SCEVParameterRewriter, const SCEV*> { public: - SCEVRewriter(ScalarEvolution &S) : SE(S) {} + static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, + ValueToValueMap &Map) { + SCEVParameterRewriter Rewriter(SE, Map); + return Rewriter.visit(Scev); + } - virtual ~SCEVRewriter() {} + SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M) + : SE(S), Map(M) {} - virtual const SCEV *visitConstant(const SCEVConstant *Constant) { + const SCEV *visitConstant(const SCEVConstant *Constant) { return Constant; } - virtual const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { + const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getTruncateExpr(Operand, Expr->getType()); } - virtual const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getZeroExtendExpr(Operand, Expr->getType()); } - virtual const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getSignExtendExpr(Operand, Expr->getType()); } - virtual const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { + const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { SmallVector<const SCEV *, 2> Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getAddExpr(Operands); } - virtual const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { + const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { SmallVector<const SCEV *, 2> Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getMulExpr(Operands); } - virtual const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { + const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS())); } - virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { SmallVector<const SCEV *, 2> Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); @@ -603,54 +616,33 @@ namespace llvm { Expr->getNoWrapFlags()); } - virtual const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { + const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { SmallVector<const SCEV *, 2> Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getSMaxExpr(Operands); } - virtual const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { + const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { SmallVector<const SCEV *, 2> Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getUMaxExpr(Operands); } - virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) { - return Expr; - } - - virtual const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { - return Expr; - } - - protected: - ScalarEvolution &SE; - }; - - typedef DenseMap<const Value*, Value*> ValueToValueMap; - - /// The SCEVParameterRewriter takes a scalar evolution expression and updates - /// the SCEVUnknown components following the Map (Value -> Value). - struct SCEVParameterRewriter: public SCEVRewriter { - public: - static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, - ValueToValueMap &Map) { - SCEVParameterRewriter Rewriter(SE, Map); - return Rewriter.visit(Scev); - } - SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M) - : SCEVRewriter(S), Map(M) {} - - virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) { + const SCEV *visitUnknown(const SCEVUnknown *Expr) { Value *V = Expr->getValue(); if (Map.count(V)) return SE.getUnknown(Map[V]); return Expr; } + const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return Expr; + } + private: + ScalarEvolution &SE; ValueToValueMap ⤅ }; @@ -658,17 +650,56 @@ namespace llvm { /// The SCEVApplyRewriter takes a scalar evolution expression and applies /// the Map (Loop -> SCEV) to all AddRecExprs. - struct SCEVApplyRewriter: public SCEVRewriter { + struct SCEVApplyRewriter + : public SCEVVisitor<SCEVApplyRewriter, const SCEV*> { public: static const SCEV *rewrite(const SCEV *Scev, LoopToScevMapT &Map, ScalarEvolution &SE) { SCEVApplyRewriter Rewriter(SE, Map); return Rewriter.visit(Scev); } + SCEVApplyRewriter(ScalarEvolution &S, LoopToScevMapT &M) - : SCEVRewriter(S), Map(M) {} + : SE(S), Map(M) {} + + const SCEV *visitConstant(const SCEVConstant *Constant) { + return Constant; + } + + const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getTruncateExpr(Operand, Expr->getType()); + } + + const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getZeroExtendExpr(Operand, Expr->getType()); + } + + const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getSignExtendExpr(Operand, Expr->getType()); + } + + const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getAddExpr(Operands); + } + + const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getMulExpr(Operands); + } - virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { + return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS())); + } + + const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { SmallVector<const SCEV *, 2> Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); @@ -683,7 +714,30 @@ namespace llvm { return Rec->evaluateAtIteration(Map[L], SE); } + const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getSMaxExpr(Operands); + } + + const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getUMaxExpr(Operands); + } + + const SCEV *visitUnknown(const SCEVUnknown *Expr) { + return Expr; + } + + const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return Expr; + } + private: + ScalarEvolution &SE; LoopToScevMapT ⤅ }; diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 21a3a12..4f47562 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -29,6 +29,7 @@ namespace llvm { class GlobalValue; +class Loop; class Type; class User; class Value; @@ -191,6 +192,36 @@ public: /// incurs significant execution cost. virtual bool isLoweredToCall(const Function *F) const; + /// Parameters that control the generic loop unrolling transformation. + struct UnrollingPreferences { + /// The cost threshold for the unrolled loop, compared to + /// CodeMetrics.NumInsts aggregated over all basic blocks in the loop body. + /// The unrolling factor is set such that the unrolled loop body does not + /// exceed this cost. Set this to UINT_MAX to disable the loop body cost + /// restriction. + unsigned Threshold; + /// The cost threshold for the unrolled loop when optimizing for size (set + /// to UINT_MAX to disable). + unsigned OptSizeThreshold; + /// A forced unrolling factor (the number of concatenated bodies of the + /// original loop in the unrolled loop body). When set to 0, the unrolling + /// transformation will select an unrolling factor based on the current cost + /// threshold and other factors. + unsigned Count; + /// Allow partial unrolling (unrolling of loops to expand the size of the + /// loop body, not only to eliminate small constant-trip-count loops). + bool Partial; + /// Allow runtime unrolling (unrolling of loops to expand the size of the + /// loop body even when the number of loop iterations is not known at compile + /// time). + bool Runtime; + }; + + /// \brief Get target-customized preferences for the generic loop unrolling + /// transformation. The caller will initialize UP with the current + /// target-independent defaults. + virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; + /// @} /// \name Scalar Target Information @@ -262,6 +293,10 @@ public: /// getPopcntSupport - Return hardware support for population count. virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; + /// haveFastSqrt -- Return true if the hardware has a fast square-root + /// instruction. + virtual bool haveFastSqrt(Type *Ty) const; + /// getIntImmCost - Return the expected cost of materializing the given /// integer immediate of the specified type. virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; @@ -279,7 +314,7 @@ public: SK_ExtractSubvector ///< ExtractSubvector Index indicates start offset. }; - /// \brief Additonal information about an operand's possible values. + /// \brief Additional information about an operand's possible values. enum OperandValueKind { OK_AnyValue, // Operand can have any value. OK_UniformValue, // Operand is uniform (splat of a value). @@ -333,6 +368,22 @@ public: unsigned Alignment, unsigned AddressSpace) const; + /// \brief Calculate the cost of performing a vector reduction. + /// + /// This is the cost of reducing the vector value of type \p Ty to a scalar + /// value using the operation denoted by \p Opcode. The form of the reduction + /// can either be a pairwise reduction or a reduction that splits the vector + /// at every reduction level. + /// + /// Pairwise: + /// (v0, v1, v2, v3) + /// ((v0+v1), (v2, v3), undef, undef) + /// Split: + /// (v0, v1, v2, v3) + /// ((v0+v2), (v1+v3), undef, undef) + virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) const; + /// \returns The cost of Intrinsic instructions. virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, ArrayRef<Type *> Tys) const; diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 3775ec9..0392f98 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -25,6 +25,7 @@ namespace llvm { class DataLayout; class StringRef; class MDNode; + class TargetLibraryInfo; /// ComputeMaskedBits - Determine which of the bits specified in Mask are /// known to be either zero or one and return them in the KnownZero/KnownOne @@ -186,7 +187,7 @@ namespace llvm { /// isKnownNonNull - Return true if this pointer couldn't possibly be null by /// its definition. This returns true for allocas, non-extern-weak globals /// and byval arguments. - bool isKnownNonNull(const Value *V); + bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = 0); } // end namespace llvm diff --git a/include/llvm/AutoUpgrade.h b/include/llvm/AutoUpgrade.h index ca3446e..c774782 100644 --- a/include/llvm/AutoUpgrade.h +++ b/include/llvm/AutoUpgrade.h @@ -15,10 +15,14 @@ #define LLVM_AUTOUPGRADE_H namespace llvm { + class CallInst; + class Constant; + class Function; + class Instruction; class Module; class GlobalVariable; - class Function; - class CallInst; + class Type; + class Value; /// This is a more granular function that simply checks an intrinsic function /// for upgrading, and returns true if it requires upgrading. It may return @@ -39,6 +43,24 @@ namespace llvm { /// This checks for global variables which should be upgraded. It returns true /// if it requires upgrading. bool UpgradeGlobalVariable(GlobalVariable *GV); + + /// If the TBAA tag for the given instruction uses the scalar TBAA format, + /// we upgrade it to the struct-path aware TBAA format. + void UpgradeInstWithTBAATag(Instruction *I); + + /// This is an auto-upgrade for bitcast between pointers with different + /// address spaces: the instruction is replaced by a pair ptrtoint+inttoptr. + Instruction *UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy, + Instruction *&Temp); + + /// This is an auto-upgrade for bitcast constant expression between pointers + /// with different address spaces: the instruction is replaced by a pair + /// ptrtoint+inttoptr. + Value *UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy); + + /// Check the debug info version number, if it is out-dated, drop the debug + /// info. Return true if module is modified. + bool UpgradeDebugInfo(Module &M); } // End llvm namespace #endif diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 463e3b9..b3d2466 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -194,7 +194,8 @@ namespace bitc { CAST_FPEXT = 8, CAST_PTRTOINT = 9, CAST_INTTOPTR = 10, - CAST_BITCAST = 11 + CAST_BITCAST = 11, + CAST_ADDRSPACECAST = 12 }; /// BinaryOpcodes - These are values used in the bitcode files to encode which @@ -368,7 +369,8 @@ namespace bitc { ATTR_KIND_UW_TABLE = 33, ATTR_KIND_Z_EXT = 34, ATTR_KIND_BUILTIN = 35, - ATTR_KIND_COLD = 36 + ATTR_KIND_COLD = 36, + ATTR_KIND_OPTIMIZE_NONE = 37 }; } // End bitc namespace diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index ce9ca0a..b2cc704 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -26,6 +26,7 @@ namespace llvm { class GlobalVariable; class TargetLowering; +class TargetLoweringBase; class SDNode; class SDValue; class SelectionDAG; @@ -88,6 +89,14 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); /// This function only tests target-independent requirements. bool isInTailCallPosition(ImmutableCallSite CS, const TargetLowering &TLI); +/// Test if given that the input instruction is in the tail call position if the +/// return type or any attributes of the function will inhibit tail call +/// optimization. +bool returnTypeIsEligibleForTailCall(const Function *F, + const Instruction *I, + const ReturnInst *Ret, + const TargetLoweringBase &TLI); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 677331b..4bda0f1 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -41,6 +41,7 @@ namespace llvm { class MCAsmInfo; class MCCFIInstruction; class MCContext; + class MCInstrInfo; class MCSection; class MCStreamer; class MCSymbol; @@ -64,6 +65,7 @@ namespace llvm { /// const MCAsmInfo *MAI; + const MCInstrInfo *MII; /// OutContext - This is the context for the output file that we are /// streaming. This owns all of the global MC-related objects for the /// generated translation unit. @@ -143,6 +145,7 @@ namespace llvm { /// getCurrentSection() - Return the current section we are emitting to. const MCSection *getCurrentSection() const; + MCSymbol *getSymbol(const GlobalValue *GV) const; //===------------------------------------------------------------------===// // MachineFunctionPass Implementation. @@ -284,6 +287,10 @@ namespace llvm { virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + /// emitImplicitDef - Targets can override this to customize the output of + /// IMPLICIT_DEF instructions in verbose mode. + virtual void emitImplicitDef(const MachineInstr *MI) const; + //===------------------------------------------------------------------===// // Symbol Lowering Routines. //===------------------------------------------------------------------===// @@ -359,13 +366,15 @@ namespace llvm { /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. This implicitly uses .set if it is available. void EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, - unsigned Size) const; + unsigned Size, + bool IsSectionRelative = false) const; /// EmitLabelReference - Emit something like ".long Label" /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. - void EmitLabelReference(const MCSymbol *Label, unsigned Size) const { - EmitLabelPlusOffset(Label, 0, Size); + void EmitLabelReference(const MCSymbol *Label, unsigned Size, + bool IsSectionRelative = false) const { + EmitLabelPlusOffset(Label, 0, Size, IsSectionRelative); } //===------------------------------------------------------------------===// @@ -449,8 +458,7 @@ namespace llvm { /// return true if the operand is erroneous. virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &OS); + const char *ExtraCode, raw_ostream &OS); private: /// Private state for PrintSpecial() @@ -462,7 +470,8 @@ namespace llvm { /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = 0, - InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const; + InlineAsm::AsmDialect AsmDialect = + InlineAsm::AD_ATT) const; /// EmitInlineAsm - This method formats and emits the specified machine /// instruction that is an inline asm. @@ -477,12 +486,13 @@ namespace llvm { void EmitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition = true) const; - void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const; + void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, - unsigned uid) const; + const MachineBasicBlock *MBB, unsigned uid) const; void EmitLLVMUsedList(const ConstantArray *InitList); + /// Emit llvm.ident metadata in an '.ident' directive. + void EmitModuleIdents(Module &M); void EmitXXStructorList(const Constant *List, bool isCtor); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); }; diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index c8ec764..0d79b1d 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -21,7 +21,9 @@ namespace llvm { class MachineBlockFrequencyInfo; class MachineLoopInfo; - /// normalizeSpillWeight - The spill weight of a live interval is computed as: + /// \brief Normalize the spill weight of a live interval + /// + /// The spill weight of a live interval is computed as: /// /// (sum(use freq) + sum(def freq)) / (K + size) /// @@ -38,44 +40,38 @@ namespace llvm { return UseDefFreq / (Size + 25*SlotIndex::InstrDist); } - /// VirtRegAuxInfo - Calculate auxiliary information for a virtual - /// register such as its spill weight and allocation hint. + /// \brief Calculate auxiliary information for a virtual register such as its + /// spill weight and allocation hint. class VirtRegAuxInfo { + public: + typedef float (*NormalizingFn)(float, unsigned); + + private: MachineFunction &MF; LiveIntervals &LIS; const MachineLoopInfo &Loops; const MachineBlockFrequencyInfo &MBFI; DenseMap<unsigned, float> Hint; + NormalizingFn normalize; + public: VirtRegAuxInfo(MachineFunction &mf, LiveIntervals &lis, const MachineLoopInfo &loops, - const MachineBlockFrequencyInfo &mbfi) - : MF(mf), LIS(lis), Loops(loops), MBFI(mbfi) {} + const MachineBlockFrequencyInfo &mbfi, + NormalizingFn norm = normalizeSpillWeight) + : MF(mf), LIS(lis), Loops(loops), MBFI(mbfi), normalize(norm) {} - /// CalculateWeightAndHint - (re)compute li's spill weight and allocation - /// hint. - void CalculateWeightAndHint(LiveInterval &li); + /// \brief (re)compute li's spill weight and allocation hint. + void calculateSpillWeightAndHint(LiveInterval &li); }; - /// CalculateSpillWeights - Compute spill weights for all virtual register + /// \brief Compute spill weights and allocation hints for all virtual register /// live intervals. - class CalculateSpillWeights : public MachineFunctionPass { - public: - static char ID; - - CalculateSpillWeights() : MachineFunctionPass(ID) { - initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); - } - - virtual void getAnalysisUsage(AnalysisUsage &au) const; - - virtual bool runOnMachineFunction(MachineFunction &fn); - - private: - /// Returns true if the given live interval is zero length. - bool isZeroLengthInterval(LiveInterval *li) const; - }; - + void calculateSpillWeightsAndHints(LiveIntervals &LIS, MachineFunction &MF, + const MachineLoopInfo &MLI, + const MachineBlockFrequencyInfo &MBFI, + VirtRegAuxInfo::NormalizingFn norm = + normalizeSpillWeight); } #endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 0c21e76..bc8dce3 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -150,7 +150,7 @@ FloatABIForCalls("float-abi", cl::opt<llvm::FPOpFusion::FPOpFusionMode> FuseFPOps("fp-contract", - cl::desc("Enable aggresive formation of fused FP ops"), + cl::desc("Enable aggressive formation of fused FP ops"), cl::init(FPOpFusion::Standard), cl::values( clEnumValN(FPOpFusion::Fast, "fast", diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 0063474..1e0ef6b 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -358,6 +358,15 @@ protected: return 0; } + /// \brief Check if \c Add is an add that can be safely folded into \c GEP. + /// + /// \c Add can be folded into \c GEP if: + /// - \c Add is an add, + /// - \c Add's size matches \c GEP's, + /// - \c Add is in the same basic block as \c GEP, and + /// - \c Add has a constant operand. + bool canFoldAddIntoGEP(const User *GEP, const Value *Add); + private: bool SelectBinaryOp(const User *I, unsigned ISDOpcode); diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 9466b90..48a0523 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -419,6 +419,10 @@ namespace ISD { /// getNode(). BITCAST, + /// ADDRSPACECAST - This operator converts between pointers of different + /// address spaces. + ADDRSPACECAST, + /// CONVERT_RNDSAT - This operator is used to support various conversions /// between various types (float, signed, unsigned and vectors of those /// types) with rounding and saturation. NOTE: Avoid using this operator as @@ -440,11 +444,11 @@ namespace ISD { /// FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, /// FLOG, FLOG2, FLOG10, FEXP, FEXP2, - /// FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary + /// FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR - Perform various unary /// floating point operations. These are inspired by libm. FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, - FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR, + FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR, /// FSINCOS - Compute both fsin and fcos as a single operation. FSINCOS, @@ -604,11 +608,17 @@ namespace ISD { ATOMIC_STORE, /// Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) + /// For double-word atomic operations: + /// ValLo, ValHi, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmpLo, cmpHi, + /// swapLo, swapHi) /// This corresponds to the cmpxchg instruction. ATOMIC_CMP_SWAP, /// Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) /// Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) + /// For double-word atomic operations: + /// ValLo, ValHi, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amtLo, amtHi) + /// ValLo, ValHi, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amtLo, amtHi) /// These correspond to the atomicrmw instruction. ATOMIC_SWAP, ATOMIC_LOAD_ADD, diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index efad0c6..3a9fef6 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -9,12 +9,12 @@ // // This file implements the LiveRange and LiveInterval classes. Given some // numbering of each the machine instructions an interval [i, j) is said to be a -// live interval for register v if there is no instruction with number j' >= j +// live range for register v if there is no instruction with number j' >= j // such that v is live at j' and there is no instruction with number i' < i such -// that v is live at i'. In this implementation intervals can have holes, -// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each -// individual range is represented as an instance of LiveRange, and the whole -// interval is represented as an instance of LiveInterval. +// that v is live at i'. In this implementation ranges can have holes, +// i.e. a range might look like [1,20), [50,65), [1000,1001). Each +// individual segment is represented as an instance of LiveRange::Segment, +// and the whole range is represented as an instance of LiveRange. // //===----------------------------------------------------------------------===// @@ -35,6 +35,7 @@ namespace llvm { class MachineRegisterInfo; class TargetRegisterInfo; class raw_ostream; + template <typename T, unsigned Small> class SmallPtrSet; /// VNInfo - Value Number Information. /// This class holds information about a machine level values, including @@ -66,7 +67,7 @@ namespace llvm { } /// Returns true if this value is defined by a PHI instruction (or was, - /// PHI instrucions may have been eliminated). + /// PHI instructions may have been eliminated). /// PHI-defs begin at a block boundary, all other defs begin at register or /// EC slots. bool isPHIDef() const { return def.isBlock(); } @@ -78,107 +79,136 @@ namespace llvm { void markUnused() { def = SlotIndex(); } }; - /// LiveRange structure - This represents a simple register range in the - /// program, with an inclusive start point and an exclusive end point. - /// These ranges are rendered as [start,end). - struct LiveRange { - SlotIndex start; // Start point of the interval (inclusive) - SlotIndex end; // End point of the interval (exclusive) - VNInfo *valno; // identifier for the value contained in this interval. + /// Result of a LiveRange query. This class hides the implementation details + /// of live ranges, and it should be used as the primary interface for + /// examining live ranges around instructions. + class LiveQueryResult { + VNInfo *const EarlyVal; + VNInfo *const LateVal; + const SlotIndex EndPoint; + const bool Kill; - LiveRange() : valno(0) {} + public: + LiveQueryResult(VNInfo *EarlyVal, VNInfo *LateVal, SlotIndex EndPoint, + bool Kill) + : EarlyVal(EarlyVal), LateVal(LateVal), EndPoint(EndPoint), Kill(Kill) + {} - LiveRange(SlotIndex S, SlotIndex E, VNInfo *V) - : start(S), end(E), valno(V) { - assert(S < E && "Cannot create empty or backwards range"); + /// Return the value that is live-in to the instruction. This is the value + /// that will be read by the instruction's use operands. Return NULL if no + /// value is live-in. + VNInfo *valueIn() const { + return EarlyVal; } - /// contains - Return true if the index is covered by this range. - /// - bool contains(SlotIndex I) const { - return start <= I && I < end; + /// Return true if the live-in value is killed by this instruction. This + /// means that either the live range ends at the instruction, or it changes + /// value. + bool isKill() const { + return Kill; } - /// containsRange - Return true if the given range, [S, E), is covered by - /// this range. - bool containsRange(SlotIndex S, SlotIndex E) const { - assert((S < E) && "Backwards interval?"); - return (start <= S && S < end) && (start < E && E <= end); + /// Return true if this instruction has a dead def. + bool isDeadDef() const { + return EndPoint.isDead(); } - bool operator<(const LiveRange &LR) const { - return start < LR.start || (start == LR.start && end < LR.end); + /// Return the value leaving the instruction, if any. This can be a + /// live-through value, or a live def. A dead def returns NULL. + VNInfo *valueOut() const { + return isDeadDef() ? 0 : LateVal; } - bool operator==(const LiveRange &LR) const { - return start == LR.start && end == LR.end; + + /// Return the value defined by this instruction, if any. This includes + /// dead defs, it is the value created by the instruction's def operands. + VNInfo *valueDefined() const { + return EarlyVal == LateVal ? 0 : LateVal; } - void dump() const; - void print(raw_ostream &os) const; + /// Return the end point of the last live range segment to interact with + /// the instruction, if any. + /// + /// The end point is an invalid SlotIndex only if the live range doesn't + /// intersect the instruction at all. + /// + /// The end point may be at or past the end of the instruction's basic + /// block. That means the value was live out of the block. + SlotIndex endPoint() const { + return EndPoint; + } }; - template <> struct isPodLike<LiveRange> { static const bool value = true; }; - - raw_ostream& operator<<(raw_ostream& os, const LiveRange &LR); - + /// This class represents the liveness of a register, stack slot, etc. + /// It manages an ordered list of Segment objects. + /// The Segments are organized in a static single assignment form: At places + /// where a new value is defined or different values reach a CFG join a new + /// segment with a new value number is used. + class LiveRange { + public: - inline bool operator<(SlotIndex V, const LiveRange &LR) { - return V < LR.start; - } + /// This represents a simple continuous liveness interval for a value. + /// The start point is inclusive, the end point exclusive. These intervals + /// are rendered as [start,end). + struct Segment { + SlotIndex start; // Start point of the interval (inclusive) + SlotIndex end; // End point of the interval (exclusive) + VNInfo *valno; // identifier for the value contained in this segment. - inline bool operator<(const LiveRange &LR, SlotIndex V) { - return LR.start < V; - } + Segment() : valno(0) {} - /// LiveInterval - This class represents some number of live ranges for a - /// register or value. This class also contains a bit of register allocator - /// state. - class LiveInterval { - public: + Segment(SlotIndex S, SlotIndex E, VNInfo *V) + : start(S), end(E), valno(V) { + assert(S < E && "Cannot create empty or backwards segment"); + } - typedef SmallVector<LiveRange,4> Ranges; - typedef SmallVector<VNInfo*,4> VNInfoList; + /// Return true if the index is covered by this segment. + bool contains(SlotIndex I) const { + return start <= I && I < end; + } - const unsigned reg; // the register or stack slot of this interval. - float weight; // weight of this interval - Ranges ranges; // the ranges in which this register is live - VNInfoList valnos; // value#'s + /// Return true if the given interval, [S, E), is covered by this segment. + bool containsInterval(SlotIndex S, SlotIndex E) const { + assert((S < E) && "Backwards interval?"); + return (start <= S && S < end) && (start < E && E <= end); + } - struct InstrSlots { - enum { - LOAD = 0, - USE = 1, - DEF = 2, - STORE = 3, - NUM = 4 - }; + bool operator<(const Segment &Other) const { + return start < Other.start || (start == Other.start && end < Other.end); + } + bool operator==(const Segment &Other) const { + return start == Other.start && end == Other.end; + } + void dump() const; }; - LiveInterval(unsigned Reg, float Weight) - : reg(Reg), weight(Weight) {} + typedef SmallVector<Segment,4> Segments; + typedef SmallVector<VNInfo*,4> VNInfoList; + + Segments segments; // the liveness segments + VNInfoList valnos; // value#'s - typedef Ranges::iterator iterator; - iterator begin() { return ranges.begin(); } - iterator end() { return ranges.end(); } + typedef Segments::iterator iterator; + iterator begin() { return segments.begin(); } + iterator end() { return segments.end(); } - typedef Ranges::const_iterator const_iterator; - const_iterator begin() const { return ranges.begin(); } - const_iterator end() const { return ranges.end(); } + typedef Segments::const_iterator const_iterator; + const_iterator begin() const { return segments.begin(); } + const_iterator end() const { return segments.end(); } typedef VNInfoList::iterator vni_iterator; vni_iterator vni_begin() { return valnos.begin(); } - vni_iterator vni_end() { return valnos.end(); } + vni_iterator vni_end() { return valnos.end(); } typedef VNInfoList::const_iterator const_vni_iterator; const_vni_iterator vni_begin() const { return valnos.begin(); } - const_vni_iterator vni_end() const { return valnos.end(); } + const_vni_iterator vni_end() const { return valnos.end(); } - /// advanceTo - Advance the specified iterator to point to the LiveRange + /// advanceTo - Advance the specified iterator to point to the Segment /// containing the specified position, or end() if the position is past the - /// end of the interval. If no LiveRange contains this position, but the + /// end of the range. If no Segment contains this position, but the /// position is in a hole, this method returns an iterator pointing to the - /// LiveRange immediately after the hole. + /// Segment immediately after the hole. iterator advanceTo(iterator I, SlotIndex Pos) { assert(I != end()); if (Pos >= endIndex()) @@ -187,22 +217,26 @@ namespace llvm { return I; } - /// find - Return an iterator pointing to the first range that ends after + /// find - Return an iterator pointing to the first segment that ends after /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster - /// when searching large intervals. + /// when searching large ranges. /// - /// If Pos is contained in a LiveRange, that range is returned. - /// If Pos is in a hole, the following LiveRange is returned. + /// If Pos is contained in a Segment, that segment is returned. + /// If Pos is in a hole, the following Segment is returned. /// If Pos is beyond endIndex, end() is returned. iterator find(SlotIndex Pos); const_iterator find(SlotIndex Pos) const { - return const_cast<LiveInterval*>(this)->find(Pos); + return const_cast<LiveRange*>(this)->find(Pos); } void clear() { valnos.clear(); - ranges.clear(); + segments.clear(); + } + + size_t size() const { + return segments.size(); } bool hasAtLeastOneValue() const { return !valnos.empty(); } @@ -220,7 +254,7 @@ namespace llvm { return valnos[ValNo]; } - /// containsValue - Returns true if VNI belongs to this interval. + /// containsValue - Returns true if VNI belongs to this range. bool containsValue(const VNInfo *VNI) const { return VNI && VNI->id < getNumValNums() && VNI == getValNumInfo(VNI->id); } @@ -234,7 +268,7 @@ namespace llvm { return VNI; } - /// createDeadDef - Make sure the interval has a value defined at Def. + /// createDeadDef - Make sure the range has a value defined at Def. /// If one already exists, return it. Otherwise allocate a new value and /// add liveness for a dead def. VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator); @@ -251,42 +285,42 @@ namespace llvm { /// RenumberValues - Renumber all values in order of appearance and remove /// unused values. - void RenumberValues(LiveIntervals &lis); + void RenumberValues(); - /// MergeValueNumberInto - This method is called when two value nubmers + /// MergeValueNumberInto - This method is called when two value numbers /// are found to be equivalent. This eliminates V1, replacing all - /// LiveRanges with the V1 value number with the V2 value number. This can + /// segments with the V1 value number with the V2 value number. This can /// cause merging of V1/V2 values numbers and compaction of the value space. VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2); - /// MergeValueInAsValue - Merge all of the live ranges of a specific val# - /// in RHS into this live interval as the specified value number. - /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the - /// current interval, it will replace the value numbers of the overlaped - /// live ranges with the specified value number. - void MergeRangesInAsValue(const LiveInterval &RHS, VNInfo *LHSValNo); - - /// MergeValueInAsValue - Merge all of the live ranges of a specific val# - /// in RHS into this live interval as the specified value number. - /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the - /// current interval, but only if the overlapping LiveRanges have the + /// Merge all of the live segments of a specific val# in RHS into this live + /// range as the specified value number. The segments in RHS are allowed + /// to overlap with segments in the current range, it will replace the + /// value numbers of the overlaped live segments with the specified value + /// number. + void MergeSegmentsInAsValue(const LiveRange &RHS, VNInfo *LHSValNo); + + /// MergeValueInAsValue - Merge all of the segments of a specific val# + /// in RHS into this live range as the specified value number. + /// The segments in RHS are allowed to overlap with segments in the + /// current range, but only if the overlapping segments have the /// specified value number. - void MergeValueInAsValue(const LiveInterval &RHS, + void MergeValueInAsValue(const LiveRange &RHS, const VNInfo *RHSValNo, VNInfo *LHSValNo); - bool empty() const { return ranges.empty(); } + bool empty() const { return segments.empty(); } - /// beginIndex - Return the lowest numbered slot covered by interval. + /// beginIndex - Return the lowest numbered slot covered. SlotIndex beginIndex() const { - assert(!empty() && "Call to beginIndex() on empty interval."); - return ranges.front().start; + assert(!empty() && "Call to beginIndex() on empty range."); + return segments.front().start; } - /// endNumber - return the maximum point of the interval of the whole, + /// endNumber - return the maximum point of the range of the whole, /// exclusive. SlotIndex endIndex() const { - assert(!empty() && "Call to endIndex() on empty interval."); - return ranges.back().end; + assert(!empty() && "Call to endIndex() on empty range."); + return segments.back().end; } bool expiredAt(SlotIndex index) const { @@ -298,31 +332,23 @@ namespace llvm { return r != end() && r->start <= index; } - /// killedAt - Return true if a live range ends at index. Note that the kill - /// point is not contained in the half-open live range. It is usually the - /// getDefIndex() slot following its last use. - bool killedAt(SlotIndex index) const { - const_iterator r = find(index.getRegSlot(true)); - return r != end() && r->end == index; - } - - /// getLiveRangeContaining - Return the live range that contains the - /// specified index, or null if there is none. - const LiveRange *getLiveRangeContaining(SlotIndex Idx) const { - const_iterator I = FindLiveRangeContaining(Idx); + /// Return the segment that contains the specified index, or null if there + /// is none. + const Segment *getSegmentContaining(SlotIndex Idx) const { + const_iterator I = FindSegmentContaining(Idx); return I == end() ? 0 : &*I; } - /// getLiveRangeContaining - Return the live range that contains the - /// specified index, or null if there is none. - LiveRange *getLiveRangeContaining(SlotIndex Idx) { - iterator I = FindLiveRangeContaining(Idx); + /// Return the live segment that contains the specified index, or null if + /// there is none. + Segment *getSegmentContaining(SlotIndex Idx) { + iterator I = FindSegmentContaining(Idx); return I == end() ? 0 : &*I; } /// getVNInfoAt - Return the VNInfo that is live at Idx, or NULL. VNInfo *getVNInfoAt(SlotIndex Idx) const { - const_iterator I = FindLiveRangeContaining(Idx); + const_iterator I = FindSegmentContaining(Idx); return I == end() ? 0 : I->valno; } @@ -330,76 +356,68 @@ namespace llvm { /// necessarilly including Idx, or NULL. Use this to find the reaching def /// used by an instruction at this SlotIndex position. VNInfo *getVNInfoBefore(SlotIndex Idx) const { - const_iterator I = FindLiveRangeContaining(Idx.getPrevSlot()); + const_iterator I = FindSegmentContaining(Idx.getPrevSlot()); return I == end() ? 0 : I->valno; } - /// FindLiveRangeContaining - Return an iterator to the live range that - /// contains the specified index, or end() if there is none. - iterator FindLiveRangeContaining(SlotIndex Idx) { + /// Return an iterator to the segment that contains the specified index, or + /// end() if there is none. + iterator FindSegmentContaining(SlotIndex Idx) { iterator I = find(Idx); return I != end() && I->start <= Idx ? I : end(); } - const_iterator FindLiveRangeContaining(SlotIndex Idx) const { + const_iterator FindSegmentContaining(SlotIndex Idx) const { const_iterator I = find(Idx); return I != end() && I->start <= Idx ? I : end(); } - /// overlaps - Return true if the intersection of the two live intervals is + /// overlaps - Return true if the intersection of the two live ranges is /// not empty. - bool overlaps(const LiveInterval& other) const { + bool overlaps(const LiveRange &other) const { if (other.empty()) return false; return overlapsFrom(other, other.begin()); } - /// overlaps - Return true if the two intervals have overlapping segments + /// overlaps - Return true if the two ranges have overlapping segments /// that are not coalescable according to CP. /// - /// Overlapping segments where one interval is defined by a coalescable + /// Overlapping segments where one range is defined by a coalescable /// copy are allowed. - bool overlaps(const LiveInterval &Other, const CoalescerPair &CP, + bool overlaps(const LiveRange &Other, const CoalescerPair &CP, const SlotIndexes&) const; - /// overlaps - Return true if the live interval overlaps a range specified + /// overlaps - Return true if the live range overlaps an interval specified /// by [Start, End). bool overlaps(SlotIndex Start, SlotIndex End) const; - /// overlapsFrom - Return true if the intersection of the two live intervals + /// overlapsFrom - Return true if the intersection of the two live ranges /// is not empty. The specified iterator is a hint that we can begin - /// scanning the Other interval starting at I. - bool overlapsFrom(const LiveInterval& other, const_iterator I) const; + /// scanning the Other range starting at I. + bool overlapsFrom(const LiveRange &Other, const_iterator I) const; - /// addRange - Add the specified LiveRange to this interval, merging - /// intervals as appropriate. This returns an iterator to the inserted live - /// range (which may have grown since it was inserted. - iterator addRange(LiveRange LR) { - return addRangeFrom(LR, ranges.begin()); + /// Add the specified Segment to this range, merging segments as + /// appropriate. This returns an iterator to the inserted segment (which + /// may have grown since it was inserted). + iterator addSegment(Segment S) { + return addSegmentFrom(S, segments.begin()); } - /// extendInBlock - If this interval is live before Kill in the basic block + /// extendInBlock - If this range is live before Kill in the basic block /// that starts at StartIdx, extend it to be live up to Kill, and return - /// the value. If there is no live range before Kill, return NULL. + /// the value. If there is no segment before Kill, return NULL. VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill); - /// join - Join two live intervals (this, and other) together. This applies - /// mappings to the value numbers in the LHS/RHS intervals as specified. If - /// the intervals are not joinable, this aborts. - void join(LiveInterval &Other, + /// join - Join two live ranges (this, and other) together. This applies + /// mappings to the value numbers in the LHS/RHS ranges as specified. If + /// the ranges are not joinable, this aborts. + void join(LiveRange &Other, const int *ValNoAssignments, const int *RHSValNoAssignments, - SmallVectorImpl<VNInfo *> &NewVNInfo, - MachineRegisterInfo *MRI); + SmallVectorImpl<VNInfo *> &NewVNInfo); - /// isInOneLiveRange - Return true if the range specified is entirely in the - /// a single LiveRange of the live interval. - bool isInOneLiveRange(SlotIndex Start, SlotIndex End) const { - const_iterator r = find(Start); - return r != end() && r->containsRange(Start, End); - } - - /// True iff this live range is a single segment that lies between the + /// True iff this segment is a single segment that lies between the /// specified boundaries, exclusively. Vregs live across a backedge are not /// considered local. The boundaries are expected to lie within an extended /// basic block, so vregs that are not live out should contain no holes. @@ -408,25 +426,63 @@ namespace llvm { endIndex() < End.getBoundaryIndex(); } - /// removeRange - Remove the specified range from this interval. Note that - /// the range must be a single LiveRange in its entirety. - void removeRange(SlotIndex Start, SlotIndex End, - bool RemoveDeadValNo = false); + /// Remove the specified segment from this range. Note that the segment + /// must be a single Segment in its entirety. + void removeSegment(SlotIndex Start, SlotIndex End, + bool RemoveDeadValNo = false); - void removeRange(LiveRange LR, bool RemoveDeadValNo = false) { - removeRange(LR.start, LR.end, RemoveDeadValNo); + void removeSegment(Segment S, bool RemoveDeadValNo = false) { + removeSegment(S.start, S.end, RemoveDeadValNo); } - /// removeValNo - Remove all the ranges defined by the specified value#. + /// Query Liveness at Idx. + /// The sub-instruction slot of Idx doesn't matter, only the instruction + /// it refers to is considered. + LiveQueryResult Query(SlotIndex Idx) const { + // Find the segment that enters the instruction. + const_iterator I = find(Idx.getBaseIndex()); + const_iterator E = end(); + if (I == E) + return LiveQueryResult(0, 0, SlotIndex(), false); + + // Is this an instruction live-in segment? + // If Idx is the start index of a basic block, include live-in segments + // that start at Idx.getBaseIndex(). + VNInfo *EarlyVal = 0; + VNInfo *LateVal = 0; + SlotIndex EndPoint; + bool Kill = false; + if (I->start <= Idx.getBaseIndex()) { + EarlyVal = I->valno; + EndPoint = I->end; + // Move to the potentially live-out segment. + if (SlotIndex::isSameInstr(Idx, I->end)) { + Kill = true; + if (++I == E) + return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill); + } + // Special case: A PHIDef value can have its def in the middle of a + // segment if the value happens to be live out of the layout + // predecessor. + // Such a value is not live-in. + if (EarlyVal->def == Idx.getBaseIndex()) + EarlyVal = 0; + } + // I now points to the segment that may be live-through, or defined by + // this instr. Ignore segments starting after the current instr. + if (!SlotIndex::isEarlierInstr(Idx, I->start)) { + LateVal = I->valno; + EndPoint = I->end; + } + return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill); + } + + /// removeValNo - Remove all the segments defined by the specified value#. /// Also remove the value# from value# list. void removeValNo(VNInfo *ValNo); - /// getSize - Returns the sum of sizes of all the LiveRange's. - /// - unsigned getSize() const; - - /// Returns true if the live interval is zero length, i.e. no live ranges - /// span instructions. It doesn't pay to spill such an interval. + /// Returns true if the live range is zero length, i.e. no live segments + /// span instructions. It doesn't pay to spill such a range. bool isZeroLength(SlotIndexes *Indexes) const { for (const_iterator i = begin(), e = end(); i != e; ++i) if (Indexes->getNextNonNullIndex(i->start).getBaseIndex() < @@ -435,27 +491,16 @@ namespace llvm { return true; } - /// isSpillable - Can this interval be spilled? - bool isSpillable() const { - return weight != HUGE_VALF; - } - - /// markNotSpillable - Mark interval as not spillable - void markNotSpillable() { - weight = HUGE_VALF; - } - - bool operator<(const LiveInterval& other) const { + bool operator<(const LiveRange& other) const { const SlotIndex &thisIndex = beginIndex(); const SlotIndex &otherIndex = other.beginIndex(); - return (thisIndex < otherIndex || - (thisIndex == otherIndex && reg < other.reg)); + return thisIndex < otherIndex; } void print(raw_ostream &OS) const; void dump() const; - /// \brief Walk the interval and assert if any invariants fail to hold. + /// \brief Walk the range and assert if any invariants fail to hold. /// /// Note that this is a no-op when asserts are disabled. #ifdef NDEBUG @@ -466,11 +511,55 @@ namespace llvm { private: - Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From); - void extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd); - Ranges::iterator extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStr); + iterator addSegmentFrom(Segment S, iterator From); + void extendSegmentEndTo(iterator I, SlotIndex NewEnd); + iterator extendSegmentStartTo(iterator I, SlotIndex NewStr); void markValNoForDeletion(VNInfo *V); + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const LiveRange &LR) { + LR.print(OS); + return OS; + } + + /// LiveInterval - This class represents the liveness of a register, + /// or stack slot. + class LiveInterval : public LiveRange { + public: + typedef LiveRange super; + + const unsigned reg; // the register or stack slot of this interval. + float weight; // weight of this interval + + LiveInterval(unsigned Reg, float Weight) + : reg(Reg), weight(Weight) {} + + /// getSize - Returns the sum of sizes of all the LiveRange's. + /// + unsigned getSize() const; + + /// isSpillable - Can this interval be spilled? + bool isSpillable() const { + return weight != llvm::huge_valf; + } + + /// markNotSpillable - Mark interval as not spillable + void markNotSpillable() { + weight = llvm::huge_valf; + } + + bool operator<(const LiveInterval& other) const { + const SlotIndex &thisIndex = beginIndex(); + const SlotIndex &otherIndex = other.beginIndex(); + return thisIndex < otherIndex || + (thisIndex == otherIndex && reg < other.reg); + } + + void print(raw_ostream &OS) const; + void dump() const; + + private: LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; }; @@ -480,54 +569,65 @@ namespace llvm { return OS; } - /// Helper class for performant LiveInterval bulk updates. + raw_ostream &operator<<(raw_ostream &OS, const LiveRange::Segment &S); + + inline bool operator<(SlotIndex V, const LiveRange::Segment &S) { + return V < S.start; + } + + inline bool operator<(const LiveRange::Segment &S, SlotIndex V) { + return S.start < V; + } + + /// Helper class for performant LiveRange bulk updates. /// - /// Calling LiveInterval::addRange() repeatedly can be expensive on large + /// Calling LiveRange::addSegment() repeatedly can be expensive on large /// live ranges because segments after the insertion point may need to be /// shifted. The LiveRangeUpdater class can defer the shifting when adding /// many segments in order. /// - /// The LiveInterval will be in an invalid state until flush() is called. + /// The LiveRange will be in an invalid state until flush() is called. class LiveRangeUpdater { - LiveInterval *LI; + LiveRange *LR; SlotIndex LastStart; - LiveInterval::iterator WriteI; - LiveInterval::iterator ReadI; - SmallVector<LiveRange, 16> Spills; + LiveRange::iterator WriteI; + LiveRange::iterator ReadI; + SmallVector<LiveRange::Segment, 16> Spills; void mergeSpills(); public: - /// Create a LiveRangeUpdater for adding segments to LI. - /// LI will temporarily be in an invalid state until flush() is called. - LiveRangeUpdater(LiveInterval *li = 0) : LI(li) {} + /// Create a LiveRangeUpdater for adding segments to LR. + /// LR will temporarily be in an invalid state until flush() is called. + LiveRangeUpdater(LiveRange *lr = 0) : LR(lr) {} ~LiveRangeUpdater() { flush(); } - /// Add a segment to LI and coalesce when possible, just like LI.addRange(). - /// Segments should be added in increasing start order for best performance. - void add(LiveRange); + /// Add a segment to LR and coalesce when possible, just like + /// LR.addSegment(). Segments should be added in increasing start order for + /// best performance. + void add(LiveRange::Segment); void add(SlotIndex Start, SlotIndex End, VNInfo *VNI) { - add(LiveRange(Start, End, VNI)); + add(LiveRange::Segment(Start, End, VNI)); } - /// Return true if the LI is currently in an invalid state, and flush() + /// Return true if the LR is currently in an invalid state, and flush() /// needs to be called. bool isDirty() const { return LastStart.isValid(); } - /// Flush the updater state to LI so it is valid and contains all added + /// Flush the updater state to LR so it is valid and contains all added /// segments. void flush(); /// Select a different destination live range. - void setDest(LiveInterval *li) { - if (LI != li && isDirty()) + void setDest(LiveRange *lr) { + if (LR != lr && isDirty()) flush(); - LI = li; + LR = lr; } /// Get the current destination live range. - LiveInterval *getDest() const { return LI; } + LiveRange *getDest() const { return LR; } void dump() const; void print(raw_ostream&) const; @@ -538,99 +638,6 @@ namespace llvm { return OS; } - /// LiveRangeQuery - Query information about a live range around a given - /// instruction. This class hides the implementation details of live ranges, - /// and it should be used as the primary interface for examining live ranges - /// around instructions. - /// - class LiveRangeQuery { - VNInfo *EarlyVal; - VNInfo *LateVal; - SlotIndex EndPoint; - bool Kill; - - public: - /// Create a LiveRangeQuery for the given live range and instruction index. - /// The sub-instruction slot of Idx doesn't matter, only the instruction it - /// refers to is considered. - LiveRangeQuery(const LiveInterval &LI, SlotIndex Idx) - : EarlyVal(0), LateVal(0), Kill(false) { - // Find the segment that enters the instruction. - LiveInterval::const_iterator I = LI.find(Idx.getBaseIndex()); - LiveInterval::const_iterator E = LI.end(); - if (I == E) - return; - // Is this an instruction live-in segment? - // If Idx is the start index of a basic block, include live-in segments - // that start at Idx.getBaseIndex(). - if (I->start <= Idx.getBaseIndex()) { - EarlyVal = I->valno; - EndPoint = I->end; - // Move to the potentially live-out segment. - if (SlotIndex::isSameInstr(Idx, I->end)) { - Kill = true; - if (++I == E) - return; - } - // Special case: A PHIDef value can have its def in the middle of a - // segment if the value happens to be live out of the layout - // predecessor. - // Such a value is not live-in. - if (EarlyVal->def == Idx.getBaseIndex()) - EarlyVal = 0; - } - // I now points to the segment that may be live-through, or defined by - // this instr. Ignore segments starting after the current instr. - if (SlotIndex::isEarlierInstr(Idx, I->start)) - return; - LateVal = I->valno; - EndPoint = I->end; - } - - /// Return the value that is live-in to the instruction. This is the value - /// that will be read by the instruction's use operands. Return NULL if no - /// value is live-in. - VNInfo *valueIn() const { - return EarlyVal; - } - - /// Return true if the live-in value is killed by this instruction. This - /// means that either the live range ends at the instruction, or it changes - /// value. - bool isKill() const { - return Kill; - } - - /// Return true if this instruction has a dead def. - bool isDeadDef() const { - return EndPoint.isDead(); - } - - /// Return the value leaving the instruction, if any. This can be a - /// live-through value, or a live def. A dead def returns NULL. - VNInfo *valueOut() const { - return isDeadDef() ? 0 : LateVal; - } - - /// Return the value defined by this instruction, if any. This includes - /// dead defs, it is the value created by the instruction's def operands. - VNInfo *valueDefined() const { - return EarlyVal == LateVal ? 0 : LateVal; - } - - /// Return the end point of the last live range segment to interact with - /// the instruction, if any. - /// - /// The end point is an invalid SlotIndex only if the live range doesn't - /// intersect the instruction at all. - /// - /// The end point may be at or past the end of the instruction's basic - /// block. That means the value was live out of the block. - SlotIndex endPoint() const { - return EndPoint; - } - }; - /// ConnectedVNInfoEqClasses - Helper class that can divide VNInfos in a /// LiveInterval into equivalence clases of connected components. A /// LiveInterval that has multiple connected components can be broken into diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index ffb07a5..d8437f0 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -90,9 +90,9 @@ namespace llvm { /// block. SmallVector<std::pair<unsigned, unsigned>, 8> RegMaskBlocks; - /// RegUnitIntervals - Keep a live interval for each register unit as a way - /// of tracking fixed physreg interference. - SmallVector<LiveInterval*, 0> RegUnitIntervals; + /// Keeps a live range set for each register unit to track fixed physreg + /// interference. + SmallVector<LiveRange*, 0> RegUnitRanges; public: static char ID; // Pass identification, replacement for typeid @@ -103,9 +103,10 @@ namespace llvm { static float getSpillWeight(bool isDef, bool isUse, BlockFrequency freq); LiveInterval &getInterval(unsigned Reg) { - LiveInterval *LI = VirtRegIntervals[Reg]; - assert(LI && "Interval does not exist for virtual register"); - return *LI; + if (hasInterval(Reg)) + return *VirtRegIntervals[Reg]; + else + return createAndComputeVirtRegInterval(Reg); } const LiveInterval &getInterval(unsigned Reg) const { @@ -117,12 +118,17 @@ namespace llvm { } // Interval creation. - LiveInterval &getOrCreateInterval(unsigned Reg) { - if (!hasInterval(Reg)) { - VirtRegIntervals.grow(Reg); - VirtRegIntervals[Reg] = createInterval(Reg); - } - return getInterval(Reg); + LiveInterval &createEmptyInterval(unsigned Reg) { + assert(!hasInterval(Reg) && "Interval already exists!"); + VirtRegIntervals.grow(Reg); + VirtRegIntervals[Reg] = createInterval(Reg); + return *VirtRegIntervals[Reg]; + } + + LiveInterval &createAndComputeVirtRegInterval(unsigned Reg) { + LiveInterval &LI = createEmptyInterval(Reg); + computeVirtRegInterval(LI); + return LI; } // Interval removal. @@ -131,10 +137,10 @@ namespace llvm { VirtRegIntervals[Reg] = 0; } - /// addLiveRangeToEndOfBlock - Given a register and an instruction, - /// adds a live range from that instruction to the end of its MBB. - LiveRange addLiveRangeToEndOfBlock(unsigned reg, - MachineInstr* startInst); + /// Given a register and an instruction, adds a live segment from that + /// instruction to the end of its MBB. + LiveInterval::Segment addSegmentToEndOfBlock(unsigned reg, + MachineInstr* startInst); /// shrinkToUses - After removing some uses of a register, shrink its live /// range to just the remaining uses. This method does not compute reaching @@ -154,7 +160,7 @@ namespace llvm { /// extended to be live out of the basic block. /// /// See also LiveRangeCalc::extend(). - void extendToIndices(LiveInterval *LI, ArrayRef<SlotIndex> Indices); + void extendToIndices(LiveRange &LR, ArrayRef<SlotIndex> Indices); /// pruneValue - If an LI value is live at Kill, prune its live range by /// removing any liveness reachable from Kill. Add live range end points to @@ -200,14 +206,14 @@ namespace llvm { return Indexes->getMBBEndIdx(mbb); } - bool isLiveInToMBB(const LiveInterval &li, + bool isLiveInToMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const { - return li.liveAt(getMBBStartIdx(mbb)); + return LR.liveAt(getMBBStartIdx(mbb)); } - bool isLiveOutOfMBB(const LiveInterval &li, + bool isLiveOutOfMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const { - return li.liveAt(getMBBEndIdx(mbb).getPrevSlot()); + return LR.liveAt(getMBBEndIdx(mbb).getPrevSlot()); } MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { @@ -225,6 +231,12 @@ namespace llvm { return Indexes->insertMachineInstrInMaps(MI); } + void InsertMachineInstrRangeInMaps(MachineBasicBlock::iterator B, + MachineBasicBlock::iterator E) { + for (MachineBasicBlock::iterator I = B; I != E; ++I) + Indexes->insertMachineInstrInMaps(I); + } + void RemoveMachineInstrFromMaps(MachineInstr *MI) { Indexes->removeMachineInstrFromMaps(MI); } @@ -352,24 +364,24 @@ namespace llvm { /// getRegUnit - Return the live range for Unit. /// It will be computed if it doesn't exist. - LiveInterval &getRegUnit(unsigned Unit) { - LiveInterval *LI = RegUnitIntervals[Unit]; - if (!LI) { + LiveRange &getRegUnit(unsigned Unit) { + LiveRange *LR = RegUnitRanges[Unit]; + if (!LR) { // Compute missing ranges on demand. - RegUnitIntervals[Unit] = LI = new LiveInterval(Unit, HUGE_VALF); - computeRegUnitInterval(LI); + RegUnitRanges[Unit] = LR = new LiveRange(); + computeRegUnitRange(*LR, Unit); } - return *LI; + return *LR; } /// getCachedRegUnit - Return the live range for Unit if it has already /// been computed, or NULL if it hasn't been computed yet. - LiveInterval *getCachedRegUnit(unsigned Unit) { - return RegUnitIntervals[Unit]; + LiveRange *getCachedRegUnit(unsigned Unit) { + return RegUnitRanges[Unit]; } - const LiveInterval *getCachedRegUnit(unsigned Unit) const { - return RegUnitIntervals[Unit]; + const LiveRange *getCachedRegUnit(unsigned Unit) const { + return RegUnitRanges[Unit]; } private: @@ -385,8 +397,8 @@ namespace llvm { void dumpInstrs() const; void computeLiveInRegUnits(); - void computeRegUnitInterval(LiveInterval*); - void computeVirtRegInterval(LiveInterval*); + void computeRegUnitRange(LiveRange&, unsigned Unit); + void computeVirtRegInterval(LiveInterval&); class HMEditor; }; diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 615b339..95933d1 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -32,7 +32,7 @@ typedef SparseBitVector<128> LiveVirtRegBitSet; /// Compare a live virtual register segment to a LiveIntervalUnion segment. inline bool -overlap(const LiveRange &VRSeg, +overlap(const LiveInterval::Segment &VRSeg, const IntervalMap<SlotIndex, LiveInterval*>::const_iterator &LUSeg) { return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end; } diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index a8749da..7edf67c 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -22,6 +22,7 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -30,10 +31,9 @@ class AliasAnalysis; class LiveIntervals; class MachineBlockFrequencyInfo; class MachineLoopInfo; -class MachineRegisterInfo; class VirtRegMap; -class LiveRangeEdit { +class LiveRangeEdit : private MachineRegisterInfo::Delegate { public: /// Callback methods for LiveRangeEdit owners. class Delegate { @@ -58,7 +58,7 @@ public: private: LiveInterval *Parent; - SmallVectorImpl<LiveInterval*> &NewRegs; + SmallVectorImpl<unsigned> &NewRegs; MachineRegisterInfo &MRI; LiveIntervals &LIS; VirtRegMap *VRM; @@ -97,6 +97,10 @@ private: /// Helper for eliminateDeadDefs. void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink); + /// MachineRegisterInfo callback to notify when new virtual + /// registers are created. + void MRI_NoteNewVirtualRegister(unsigned VReg); + public: /// Create a LiveRangeEdit for breaking down parent into smaller pieces. /// @param parent The register being spilled or split. @@ -108,7 +112,7 @@ public: /// function. If NULL, no virtual register map updates will /// be done. This could be the case if called before Regalloc. LiveRangeEdit(LiveInterval *parent, - SmallVectorImpl<LiveInterval*> &newRegs, + SmallVectorImpl<unsigned> &newRegs, MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm, @@ -118,7 +122,9 @@ public: TII(*MF.getTarget().getInstrInfo()), TheDelegate(delegate), FirstNew(newRegs.size()), - ScannedRemattable(false) {} + ScannedRemattable(false) { MRI.setDelegate(this); } + + ~LiveRangeEdit() { MRI.resetDelegate(this); } LiveInterval &getParent() const { assert(Parent && "No parent LiveInterval"); @@ -127,23 +133,30 @@ public: unsigned getReg() const { return getParent().reg; } /// Iterator for accessing the new registers added by this edit. - typedef SmallVectorImpl<LiveInterval*>::const_iterator iterator; + typedef SmallVectorImpl<unsigned>::const_iterator iterator; iterator begin() const { return NewRegs.begin()+FirstNew; } iterator end() const { return NewRegs.end(); } unsigned size() const { return NewRegs.size()-FirstNew; } bool empty() const { return size() == 0; } - LiveInterval *get(unsigned idx) const { return NewRegs[idx+FirstNew]; } + unsigned get(unsigned idx) const { return NewRegs[idx+FirstNew]; } - ArrayRef<LiveInterval*> regs() const { + ArrayRef<unsigned> regs() const { return makeArrayRef(NewRegs).slice(FirstNew); } + /// createEmptyIntervalFrom - Create a new empty interval based on OldReg. + LiveInterval &createEmptyIntervalFrom(unsigned OldReg); + /// createFrom - Create a new virtual register based on OldReg. - LiveInterval &createFrom(unsigned OldReg); + unsigned createFrom(unsigned OldReg); /// create - Create a new register with the same class and original slot as /// parent. - LiveInterval &create() { + LiveInterval &createEmptyInterval() { + return createEmptyIntervalFrom(getReg()); + } + + unsigned create() { return createFrom(getReg()); } diff --git a/include/llvm/CodeGen/LiveRegUnits.h b/include/llvm/CodeGen/LiveRegUnits.h new file mode 100644 index 0000000..02b9c55 --- /dev/null +++ b/include/llvm/CodeGen/LiveRegUnits.h @@ -0,0 +1,88 @@ +//===-- llvm/CodeGen/LiveRegUnits.h - Live register unit set ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a Set of live register units. This can be used for ad +// hoc liveness tracking after register allocation. You can start with the +// live-ins/live-outs at the beginning/end of a block and update the information +// while walking the instructions inside the block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEREGUNITS_H +#define LLVM_CODEGEN_LIVEREGUNITS_H + +#include "llvm/ADT/SparseSet.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include <cassert> + +namespace llvm { + +class MachineInstr; + +/// A set of live register units with functions to track liveness when walking +/// backward/forward through a basic block. +class LiveRegUnits { + SparseSet<unsigned> LiveUnits; + + LiveRegUnits(const LiveRegUnits&) LLVM_DELETED_FUNCTION; + LiveRegUnits &operator=(const LiveRegUnits&) LLVM_DELETED_FUNCTION; +public: + /// \brief Constructs a new empty LiveRegUnits set. + LiveRegUnits() {} + + void init(const TargetRegisterInfo *TRI) { + LiveUnits.clear(); + LiveUnits.setUniverse(TRI->getNumRegs()); + } + + void clear() { LiveUnits.clear(); } + + bool empty() const { return LiveUnits.empty(); } + + /// \brief Adds a register to the set. + void addReg(unsigned Reg, const MCRegisterInfo &MCRI) { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) + LiveUnits.insert(*RUnits); + } + + /// \brief Removes a register from the set. + void removeReg(unsigned Reg, const MCRegisterInfo &MCRI) { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) + LiveUnits.erase(*RUnits); + } + + /// \brief Removes registers clobbered by the regmask operand @p Op. + void removeRegsInMask(const MachineOperand &Op, const MCRegisterInfo &MCRI); + + /// \brief Returns true if register @p Reg (or one of its super register) is + /// contained in the set. + bool contains(unsigned Reg, const MCRegisterInfo &MCRI) const { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) { + if (LiveUnits.count(*RUnits)) + return true; + } + return false; + } + + /// \brief Simulates liveness when stepping backwards over an + /// instruction(bundle): Remove Defs, add uses. + void stepBackward(const MachineInstr &MI, const MCRegisterInfo &MCRI); + + /// \brief Simulates liveness when stepping forward over an + /// instruction(bundle): Remove killed-uses, add defs. + void stepForward(const MachineInstr &MI, const MCRegisterInfo &MCRI); + + /// \brief Adds all registers in the live-in list of block @p BB. + void addLiveIns(const MachineBasicBlock *MBB, const MCRegisterInfo &MCRI); +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index d6f5883..7717809 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -410,8 +410,8 @@ public: /// branch to do so (e.g., a table jump). True is a conservative answer. bool canFallThrough(); - /// Returns a pointer to the first instructon in this block that is not a - /// PHINode instruction. When adding instruction to the beginning of the + /// Returns a pointer to the first instruction in this block that is not a + /// PHINode instruction. When adding instructions to the beginning of the /// basic block, they should be added before the returned value, not before /// the first instruction, which might be PHI. /// Returns end() is there's no non-PHI instruction. @@ -733,6 +733,31 @@ template <> struct GraphTraits<Inverse<const MachineBasicBlock*> > { } }; + + +/// MachineInstrSpan provides an interface to get an iteration range +/// containing the instruction it was initialized with, along with all +/// those instructions inserted prior to or following that instruction +/// at some point after the MachineInstrSpan is constructed. +class MachineInstrSpan { + MachineBasicBlock &MBB; + MachineBasicBlock::iterator I, B, E; +public: + MachineInstrSpan(MachineBasicBlock::iterator I) + : MBB(*I->getParent()), + I(I), + B(I == MBB.begin() ? MBB.end() : llvm::prior(I)), + E(llvm::next(I)) {} + + MachineBasicBlock::iterator begin() { + return B == MBB.end() ? MBB.begin() : llvm::next(B); + } + MachineBasicBlock::iterator end() { return E; } + bool empty() { return begin() == end(); } + + MachineBasicBlock::iterator getInitial() { return I; } +}; + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index 98dd03b..c59948f 100644 --- a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -1,4 +1,4 @@ -//==- MachineBranchProbabilityInfo.h - Machine Branch Probability Analysis -==// +//=- MachineBranchProbabilityInfo.h - Branch Probability Analysis -*- C++ -*-=// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index cf5e7e2..cccab81 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -397,8 +397,8 @@ public: return isBranch(Type) & isBarrier(Type) & !isIndirectBranch(Type); } - // isPredicable - Return true if this instruction has a predicate operand that - // controls execution. It may be set to 'always', or may be set to other + /// Return true if this instruction has a predicate operand that + /// controls execution. It may be set to 'always', or may be set to other /// values. There are various methods in TargetInstrInfo that can be used to /// control and modify the predicate in this instruction. bool isPredicable(QueryType Type = AllInBundle) const { @@ -637,6 +637,13 @@ public: bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } + /// A DBG_VALUE is indirect iff the first operand is a register and + /// the second operand is an immediate. + bool isIndirectDebugValue() const { + return isDebugValue() + && getOperand(0).isReg() + && getOperand(1).isImm(); + } bool isPHI() const { return getOpcode() == TargetOpcode::PHI; } bool isKill() const { return getOpcode() == TargetOpcode::KILL; } @@ -886,13 +893,12 @@ public: /// Look for the operand that defines it and mark it as IsDead. If /// AddIfNotFound is true, add a implicit operand if it's not found. Returns /// true if the operand exists / is added. - bool addRegisterDead(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, + bool addRegisterDead(unsigned Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound = false); /// addRegisterDefined - We have determined MI defines a register. Make sure /// there is an operand defining Reg. - void addRegisterDefined(unsigned IncomingReg, - const TargetRegisterInfo *RegInfo = 0); + void addRegisterDefined(unsigned Reg, const TargetRegisterInfo *RegInfo = 0); /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as /// dead except those in the UsedRegs list. diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 186017c..460c08c 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -234,7 +234,7 @@ public: /// \brief Returns a reference to a list of cfi instructions in the current /// function's prologue. Used to construct frame maps for debug and exception /// handling comsumers. - const std::vector<MCCFIInstruction> &getFrameInstructions() { + const std::vector<MCCFIInstruction> &getFrameInstructions() const { return FrameInstructions; } diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 57b28fe..40f3580 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -564,6 +564,8 @@ public: unsigned SubReg = 0, bool isDebug = false, bool isInternalRead = false) { + assert(!(isDead && !isDef) && "Dead flag on non-def"); + assert(!(isKill && isDef) && "Kill flag on def"); MachineOperand Op(MachineOperand::MO_Register); Op.IsDef = isDef; Op.IsImp = isImp; diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 7a6dcd0..58ca907 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -22,12 +22,24 @@ #include <vector> namespace llvm { +class PSetIterator; /// MachineRegisterInfo - Keep track of information for virtual and physical /// registers, including vreg register classes, use/def chains for registers, /// etc. class MachineRegisterInfo { +public: + class Delegate { + virtual void anchor(); + public: + virtual void MRI_NoteNewVirtualRegister(unsigned Reg) = 0; + + virtual ~Delegate() {} + }; + +private: const TargetMachine &TM; + Delegate *TheDelegate; /// IsSSA - True when the machine function is in SSA form and virtual /// registers have a single def. @@ -116,6 +128,23 @@ public: return TM.getRegisterInfo(); } + void resetDelegate(Delegate *delegate) { + // Ensure another delegate does not take over unless the current + // delegate first unattaches itself. If we ever need to multicast + // notifications, we will need to change to using a list. + assert(TheDelegate == delegate && + "Only the current delegate can perform reset!"); + TheDelegate = 0; + } + + void setDelegate(Delegate *delegate) { + assert(delegate && !TheDelegate && + "Attempted to set delegate to null, or to change it without " + "first resetting it!"); + + TheDelegate = delegate; + } + //===--------------------------------------------------------------------===// // Function State //===--------------------------------------------------------------------===// @@ -299,6 +328,11 @@ public: /// a physreg. bool isConstantPhysReg(unsigned PhysReg, const MachineFunction &MF) const; + /// Get an iterator over the pressure sets affected by the given physical or + /// virtual register. If RegUnit is physical, it must be a register unit (from + /// MCRegUnitIterator). + PSetIterator getPressureSets(unsigned RegUnit) const; + //===--------------------------------------------------------------------===// // Virtual Register Info //===--------------------------------------------------------------------===// @@ -620,9 +654,49 @@ public: return Op->getParent(); } }; +}; + +/// Iterate over the pressure sets affected by the given physical or virtual +/// register. If Reg is physical, it must be a register unit (from +/// MCRegUnitIterator). +class PSetIterator { + const int *PSet; + unsigned Weight; +public: + PSetIterator(): PSet(0), Weight(0) {} + PSetIterator(unsigned RegUnit, const MachineRegisterInfo *MRI) { + const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); + if (TargetRegisterInfo::isVirtualRegister(RegUnit)) { + const TargetRegisterClass *RC = MRI->getRegClass(RegUnit); + PSet = TRI->getRegClassPressureSets(RC); + Weight = TRI->getRegClassWeight(RC).RegWeight; + } + else { + PSet = TRI->getRegUnitPressureSets(RegUnit); + Weight = TRI->getRegUnitWeight(RegUnit); + } + if (*PSet == -1) + PSet = 0; + } + bool isValid() const { return PSet; } + + unsigned getWeight() const { return Weight; } + + unsigned operator*() const { return *PSet; } + void operator++() { + assert(isValid() && "Invalid PSetIterator."); + ++PSet; + if (*PSet == -1) + PSet = 0; + } }; +inline PSetIterator MachineRegisterInfo:: +getPressureSets(unsigned RegUnit) const { + return PSetIterator(RegUnit, this); +} + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/MachineRelocation.h b/include/llvm/CodeGen/MachineRelocation.h index 244b466..e778457 100644 --- a/include/llvm/CodeGen/MachineRelocation.h +++ b/include/llvm/CodeGen/MachineRelocation.h @@ -57,7 +57,7 @@ class MachineRelocation { union { void *Result; // If this has been resolved to a resolved pointer GlobalValue *GV; // If this is a pointer to a GV or an indirect ref. - MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB + MachineBasicBlock *MBB; // If this is a pointer to an LLVM BB const char *ExtSym; // If this is a pointer to a named symbol unsigned Index; // Constant pool / jump table index unsigned GOTIndex; // Index in the GOT of this symbol/global diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index d110ea1..7782895 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -7,8 +7,48 @@ // //===----------------------------------------------------------------------===// // -// This file provides a MachineSchedRegistry for registering alternative machine -// schedulers. A Target may provide an alternative scheduler implementation by +// This file provides an interface for customizing the standard MachineScheduler +// pass. Note that the entire pass may be replaced as follows: +// +// <Target>TargetMachine::createPassConfig(PassManagerBase &PM) { +// PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID); +// ...} +// +// The MachineScheduler pass is only responsible for choosing the regions to be +// scheduled. Targets can override the DAG builder and scheduler without +// replacing the pass as follows: +// +// ScheduleDAGInstrs *<Target>PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// return new CustomMachineScheduler(C); +// } +// +// The default scheduler, ScheduleDAGMI, builds the DAG and drives list +// scheduling while updating the instruction stream, register pressure, and live +// intervals. Most targets don't need to override the DAG builder and list +// schedulier, but subtargets that require custom scheduling heuristics may +// plugin an alternate MachineSchedStrategy. The strategy is responsible for +// selecting the highest priority node from the list: +// +// ScheduleDAGInstrs *<Target>PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// return new ScheduleDAGMI(C, CustomStrategy(C)); +// } +// +// The DAG builder can also be customized in a sense by adding DAG mutations +// that will run after DAG building and before list scheduling. DAG mutations +// can adjust dependencies based on target-specific knowledge or add weak edges +// to aid heuristics: +// +// ScheduleDAGInstrs *<Target>PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// ScheduleDAGMI *DAG = new ScheduleDAGMI(C, CustomStrategy(C)); +// DAG->addMutation(new CustomDependencies(DAG->TII, DAG->TRI)); +// return DAG; +// } +// +// A target that supports alternative schedulers can use the +// MachineSchedRegistry to allow command line selection. This can be done by // implementing the following boilerplate: // // static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) { @@ -18,9 +58,19 @@ // SchedCustomRegistry("custom", "Run my target's custom scheduler", // createCustomMachineSched); // -// Inside <Target>PassConfig: -// enablePass(&MachineSchedulerID); -// MachineSchedRegistry::setDefault(createCustomMachineSched); +// +// Finally, subtargets that don't need to implement custom heuristics but would +// like to configure the GenericScheduler's policy for a given scheduler region, +// including scheduling direction and register pressure tracking policy, can do +// this: +// +// void <SubTarget>Subtarget:: +// overrideSchedPolicy(MachineSchedPolicy &Policy, +// MachineInstr *begin, +// MachineInstr *end, +// unsigned NumRegionInstrs) const { +// Policy.<Flag> = true; +// } // //===----------------------------------------------------------------------===// @@ -85,15 +135,6 @@ public: static MachineSchedRegistry *getList() { return (MachineSchedRegistry *)Registry.getList(); } - static ScheduleDAGCtor getDefault() { - return (ScheduleDAGCtor)Registry.getDefault(); - } - static void setDefault(ScheduleDAGCtor C) { - Registry.setDefault((MachinePassCtor)C); - } - static void setDefault(StringRef Name) { - Registry.setDefault(Name); - } static void setListener(MachinePassRegistryListener *L) { Registry.setListener(L); } @@ -101,12 +142,41 @@ public: class ScheduleDAGMI; +/// Define a generic scheduling policy for targets that don't provide their own +/// MachineSchedStrategy. This can be overriden for each scheduling region +/// before building the DAG. +struct MachineSchedPolicy { + // Allow the scheduler to disable register pressure tracking. + bool ShouldTrackPressure; + + // Allow the scheduler to force top-down or bottom-up scheduling. If neither + // is true, the scheduler runs in both directions and converges. + bool OnlyTopDown; + bool OnlyBottomUp; + + MachineSchedPolicy(): + ShouldTrackPressure(false), OnlyTopDown(false), OnlyBottomUp(false) {} +}; + /// MachineSchedStrategy - Interface to the scheduling algorithm used by /// ScheduleDAGMI. +/// +/// Initialization sequence: +/// initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots class MachineSchedStrategy { + virtual void anchor(); public: virtual ~MachineSchedStrategy() {} + /// Optionally override the per-region scheduling policy. + virtual void initPolicy(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned NumRegionInstrs) {} + + /// Check if pressure tracking is needed before building the DAG and + /// initializing this strategy. Called after initPolicy. + virtual bool shouldTrackPressure() const { return true; } + /// Initialize the strategy after building the DAG for a new region. virtual void initialize(ScheduleDAGMI *DAG) = 0; @@ -193,6 +263,7 @@ public: /// Mutate the DAG as a postpass after normal DAG building. class ScheduleDAGMutation { + virtual void anchor(); public: virtual ~ScheduleDAGMutation() {} @@ -221,14 +292,20 @@ protected: MachineBasicBlock::iterator LiveRegionEnd; - /// Register pressure in this region computed by buildSchedGraph. + // Map each SU to its summary of pressure changes. This array is updated for + // liveness during bottom-up scheduling. Top-down scheduling may proceed but + // has no affect on the pressure diffs. + PressureDiffs SUPressureDiffs; + + /// Register pressure in this region computed by initRegPressure. + bool ShouldTrackPressure; IntervalPressure RegPressure; RegPressureTracker RPTracker; /// List of pressure sets that exceed the target's pressure limit before /// scheduling, listed in increasing set ID order. Each pressure set is paired /// with its max pressure in the currently scheduled regions. - std::vector<PressureElement> RegionCriticalPSets; + std::vector<PressureChange> RegionCriticalPSets; /// The top of the unscheduled zone. MachineBasicBlock::iterator CurrentTop; @@ -254,8 +331,9 @@ public: ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S): ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), DFSResult(0), - Topo(SUnits, &ExitSU), RPTracker(RegPressure), CurrentTop(), - TopRPTracker(TopPressure), CurrentBottom(), BotRPTracker(BotPressure), + Topo(SUnits, &ExitSU), ShouldTrackPressure(false), + RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure), + CurrentBottom(), BotRPTracker(BotPressure), NextClusterPred(NULL), NextClusterSucc(NULL) { #ifndef NDEBUG NumInstrsScheduled = 0; @@ -264,6 +342,9 @@ public: virtual ~ScheduleDAGMI(); + /// \brief Return true if register pressure tracking is enabled. + bool isTrackingPressure() const { return ShouldTrackPressure; } + /// Add a postprocessing step to the DAG builder. /// Mutations are applied in the order that they are added after normal DAG /// building and before MachineSchedStrategy initialization. @@ -293,8 +374,7 @@ public: void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, - unsigned endcount); - + unsigned regioninstrs) LLVM_OVERRIDE; /// Implement ScheduleDAGInstrs interface for scheduling a sequence of /// reorderable instructions. @@ -315,10 +395,14 @@ public: /// Get register pressure for the entire scheduling region before scheduling. const IntervalPressure &getRegPressure() const { return RegPressure; } - const std::vector<PressureElement> &getRegionCriticalPSets() const { + const std::vector<PressureChange> &getRegionCriticalPSets() const { return RegionCriticalPSets; } + PressureDiff &getPressureDiff(const SUnit *SU) { + return SUPressureDiffs[SU->NodeNum]; + } + const SUnit *getNextClusterPred() const { return NextClusterPred; } const SUnit *getNextClusterSucc() const { return NextClusterSucc; } @@ -332,6 +416,9 @@ public: BitVector &getScheduledTrees() { return ScheduledTrees; } + /// Compute the cyclic critical path through the DAG. + unsigned computeCyclicCriticalPath(); + void viewGraph(const Twine &Name, const Twine &Title) LLVM_OVERRIDE; void viewGraph() LLVM_OVERRIDE; @@ -367,7 +454,10 @@ protected: void initRegPressure(); - void updateScheduledPressure(const std::vector<unsigned> &NewMaxPressure); + void updatePressureDiffs(ArrayRef<unsigned> LiveUses); + + void updateScheduledPressure(const SUnit *SU, + const std::vector<unsigned> &NewMaxPressure); bool checkSchedLimit(); diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index b57abca..aca0a91 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -20,79 +20,63 @@ #include "llvm/ADT/ilist_node.h" #include <list> #include <map> +#include <set> namespace PBQP { /// PBQP Graph class. /// Instances of this class describe PBQP problems. class Graph { - private: - - // ----- TYPEDEFS ----- - class NodeEntry; - class EdgeEntry; - - typedef llvm::ilist<NodeEntry> NodeList; - typedef llvm::ilist<EdgeEntry> EdgeList; - public: - typedef NodeList::iterator NodeItr; - typedef NodeList::const_iterator ConstNodeItr; - - typedef EdgeList::iterator EdgeItr; - typedef EdgeList::const_iterator ConstEdgeItr; + typedef unsigned NodeId; + typedef unsigned EdgeId; private: - typedef std::list<EdgeItr> AdjEdgeList; - + typedef std::set<NodeId> AdjEdgeList; + public: typedef AdjEdgeList::iterator AdjEdgeItr; private: - class NodeEntry : public llvm::ilist_node<NodeEntry> { - friend struct llvm::ilist_sentinel_traits<NodeEntry>; + class NodeEntry { private: - Vector costs; + Vector costs; AdjEdgeList adjEdges; - unsigned degree; void *data; NodeEntry() : costs(0, 0) {} public: - NodeEntry(const Vector &costs) : costs(costs), degree(0) {} + NodeEntry(const Vector &costs) : costs(costs), data(0) {} Vector& getCosts() { return costs; } const Vector& getCosts() const { return costs; } - unsigned getDegree() const { return degree; } + unsigned getDegree() const { return adjEdges.size(); } AdjEdgeItr edgesBegin() { return adjEdges.begin(); } AdjEdgeItr edgesEnd() { return adjEdges.end(); } - AdjEdgeItr addEdge(EdgeItr e) { - ++degree; + AdjEdgeItr addEdge(EdgeId e) { return adjEdges.insert(adjEdges.end(), e); } void removeEdge(AdjEdgeItr ae) { - --degree; adjEdges.erase(ae); } void setData(void *data) { this->data = data; } void* getData() { return data; } }; - class EdgeEntry : public llvm::ilist_node<EdgeEntry> { - friend struct llvm::ilist_sentinel_traits<EdgeEntry>; + class EdgeEntry { private: - NodeItr node1, node2; + NodeId node1, node2; Matrix costs; AdjEdgeItr node1AEItr, node2AEItr; void *data; - EdgeEntry() : costs(0, 0, 0) {} + EdgeEntry() : costs(0, 0, 0), data(0) {} public: - EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs) + EdgeEntry(NodeId node1, NodeId node2, const Matrix &costs) : node1(node1), node2(node2), costs(costs) {} - NodeItr getNode1() const { return node1; } - NodeItr getNode2() const { return node2; } + NodeId getNode1() const { return node1; } + NodeId getNode2() const { return node2; } Matrix& getCosts() { return costs; } const Matrix& getCosts() const { return costs; } void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; } @@ -105,254 +89,305 @@ namespace PBQP { // ----- MEMBERS ----- - NodeList nodes; - unsigned numNodes; + typedef std::vector<NodeEntry> NodeVector; + typedef std::vector<NodeId> FreeNodeVector; + NodeVector nodes; + FreeNodeVector freeNodes; - EdgeList edges; - unsigned numEdges; + typedef std::vector<EdgeEntry> EdgeVector; + typedef std::vector<EdgeId> FreeEdgeVector; + EdgeVector edges; + FreeEdgeVector freeEdges; // ----- INTERNAL METHODS ----- - NodeEntry& getNode(NodeItr nItr) { return *nItr; } - const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; } - - EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; } - const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; } - - NodeItr addConstructedNode(const NodeEntry &n) { - ++numNodes; - return nodes.insert(nodes.end(), n); + NodeEntry& getNode(NodeId nId) { return nodes[nId]; } + const NodeEntry& getNode(NodeId nId) const { return nodes[nId]; } + + EdgeEntry& getEdge(EdgeId eId) { return edges[eId]; } + const EdgeEntry& getEdge(EdgeId eId) const { return edges[eId]; } + + NodeId addConstructedNode(const NodeEntry &n) { + NodeId nodeId = 0; + if (!freeNodes.empty()) { + nodeId = freeNodes.back(); + freeNodes.pop_back(); + nodes[nodeId] = n; + } else { + nodeId = nodes.size(); + nodes.push_back(n); + } + return nodeId; } - EdgeItr addConstructedEdge(const EdgeEntry &e) { - assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() && + EdgeId addConstructedEdge(const EdgeEntry &e) { + assert(findEdge(e.getNode1(), e.getNode2()) == invalidEdgeId() && "Attempt to add duplicate edge."); - ++numEdges; - EdgeItr edgeItr = edges.insert(edges.end(), e); - EdgeEntry &ne = getEdge(edgeItr); + EdgeId edgeId = 0; + if (!freeEdges.empty()) { + edgeId = freeEdges.back(); + freeEdges.pop_back(); + edges[edgeId] = e; + } else { + edgeId = edges.size(); + edges.push_back(e); + } + + EdgeEntry &ne = getEdge(edgeId); NodeEntry &n1 = getNode(ne.getNode1()); NodeEntry &n2 = getNode(ne.getNode2()); + // Sanity check on matrix dimensions: assert((n1.getCosts().getLength() == ne.getCosts().getRows()) && (n2.getCosts().getLength() == ne.getCosts().getCols()) && "Edge cost dimensions do not match node costs dimensions."); - ne.setNode1AEItr(n1.addEdge(edgeItr)); - ne.setNode2AEItr(n2.addEdge(edgeItr)); - return edgeItr; + + ne.setNode1AEItr(n1.addEdge(edgeId)); + ne.setNode2AEItr(n2.addEdge(edgeId)); + return edgeId; } - inline void copyFrom(const Graph &other); + Graph(const Graph &other) {} + void operator=(const Graph &other) {} + public: - /// \brief Construct an empty PBQP graph. - Graph() : numNodes(0), numEdges(0) {} + class NodeItr { + public: + NodeItr(NodeId nodeId, const Graph &g) + : nodeId(nodeId), endNodeId(g.nodes.size()), freeNodes(g.freeNodes) { + this->nodeId = findNextInUse(nodeId); // Move to the first in-use nodeId + } - /// \brief Copy construct this graph from "other". Note: Does not copy node - /// and edge data, only graph structure and costs. - /// @param other Source graph to copy from. - Graph(const Graph &other) : numNodes(0), numEdges(0) { - copyFrom(other); - } + bool operator==(const NodeItr& n) const { return nodeId == n.nodeId; } + bool operator!=(const NodeItr& n) const { return !(*this == n); } + NodeItr& operator++() { nodeId = findNextInUse(++nodeId); return *this; } + NodeId operator*() const { return nodeId; } - /// \brief Make this graph a copy of "other". Note: Does not copy node and - /// edge data, only graph structure and costs. - /// @param other The graph to copy from. - /// @return A reference to this graph. - /// - /// This will clear the current graph, erasing any nodes and edges added, - /// before copying from other. - Graph& operator=(const Graph &other) { - clear(); - copyFrom(other); - return *this; - } + private: + NodeId findNextInUse(NodeId n) const { + while (n < endNodeId && + std::find(freeNodes.begin(), freeNodes.end(), n) != + freeNodes.end()) { + ++n; + } + return n; + } + + NodeId nodeId, endNodeId; + const FreeNodeVector& freeNodes; + }; + + class EdgeItr { + public: + EdgeItr(EdgeId edgeId, const Graph &g) + : edgeId(edgeId), endEdgeId(g.edges.size()), freeEdges(g.freeEdges) { + this->edgeId = findNextInUse(edgeId); // Move to the first in-use edgeId + } + + bool operator==(const EdgeItr& n) const { return edgeId == n.edgeId; } + bool operator!=(const EdgeItr& n) const { return !(*this == n); } + EdgeItr& operator++() { edgeId = findNextInUse(++edgeId); return *this; } + EdgeId operator*() const { return edgeId; } + + private: + EdgeId findNextInUse(EdgeId n) const { + while (n < endEdgeId && + std::find(freeEdges.begin(), freeEdges.end(), n) != + freeEdges.end()) { + ++n; + } + return n; + } + + EdgeId edgeId, endEdgeId; + const FreeEdgeVector& freeEdges; + }; + + /// \brief Construct an empty PBQP graph. + Graph() {} /// \brief Add a node with the given costs. /// @param costs Cost vector for the new node. /// @return Node iterator for the added node. - NodeItr addNode(const Vector &costs) { + NodeId addNode(const Vector &costs) { return addConstructedNode(NodeEntry(costs)); } /// \brief Add an edge between the given nodes with the given costs. - /// @param n1Itr First node. - /// @param n2Itr Second node. + /// @param n1Id First node. + /// @param n2Id Second node. /// @return Edge iterator for the added edge. - EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr, - const Matrix &costs) { - assert(getNodeCosts(n1Itr).getLength() == costs.getRows() && - getNodeCosts(n2Itr).getLength() == costs.getCols() && + EdgeId addEdge(NodeId n1Id, NodeId n2Id, const Matrix &costs) { + assert(getNodeCosts(n1Id).getLength() == costs.getRows() && + getNodeCosts(n2Id).getLength() == costs.getCols() && "Matrix dimensions mismatch."); - return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs)); + return addConstructedEdge(EdgeEntry(n1Id, n2Id, costs)); } /// \brief Get the number of nodes in the graph. /// @return Number of nodes in the graph. - unsigned getNumNodes() const { return numNodes; } + unsigned getNumNodes() const { return nodes.size() - freeNodes.size(); } /// \brief Get the number of edges in the graph. /// @return Number of edges in the graph. - unsigned getNumEdges() const { return numEdges; } + unsigned getNumEdges() const { return edges.size() - freeEdges.size(); } /// \brief Get a node's cost vector. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Node cost vector. - Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); } + Vector& getNodeCosts(NodeId nId) { return getNode(nId).getCosts(); } /// \brief Get a node's cost vector (const version). - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Node cost vector. - const Vector& getNodeCosts(ConstNodeItr nItr) const { - return getNode(nItr).getCosts(); + const Vector& getNodeCosts(NodeId nId) const { + return getNode(nId).getCosts(); } /// \brief Set a node's data pointer. - /// @param nItr Node iterator. + /// @param nId Node id. /// @param data Pointer to node data. /// /// Typically used by a PBQP solver to attach data to aid in solution. - void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); } + void setNodeData(NodeId nId, void *data) { getNode(nId).setData(data); } /// \brief Get the node's data pointer. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Pointer to node data. - void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); } - + void* getNodeData(NodeId nId) { return getNode(nId).getData(); } + /// \brief Get an edge's cost matrix. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return Edge cost matrix. - Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); } + Matrix& getEdgeCosts(EdgeId eId) { return getEdge(eId).getCosts(); } /// \brief Get an edge's cost matrix (const version). - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return Edge cost matrix. - const Matrix& getEdgeCosts(ConstEdgeItr eItr) const { - return getEdge(eItr).getCosts(); + const Matrix& getEdgeCosts(EdgeId eId) const { + return getEdge(eId).getCosts(); } /// \brief Set an edge's data pointer. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @param data Pointer to edge data. /// /// Typically used by a PBQP solver to attach data to aid in solution. - void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); } + void setEdgeData(EdgeId eId, void *data) { getEdge(eId).setData(data); } /// \brief Get an edge's data pointer. - /// @param eItr Edge iterator. - /// @return Pointer to edge data. - void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); } + /// @param eId Edge id. + /// @return Pointer to edge data. + void* getEdgeData(EdgeId eId) { return getEdge(eId).getData(); } /// \brief Get a node's degree. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return The degree of the node. - unsigned getNodeDegree(NodeItr nItr) const { - return getNode(nItr).getDegree(); + unsigned getNodeDegree(NodeId nId) const { + return getNode(nId).getDegree(); } /// \brief Begin iterator for node set. - NodeItr nodesBegin() { return nodes.begin(); } - - /// \brief Begin const iterator for node set. - ConstNodeItr nodesBegin() const { return nodes.begin(); } + NodeItr nodesBegin() const { return NodeItr(0, *this); } /// \brief End iterator for node set. - NodeItr nodesEnd() { return nodes.end(); } - - /// \brief End const iterator for node set. - ConstNodeItr nodesEnd() const { return nodes.end(); } + NodeItr nodesEnd() const { return NodeItr(nodes.size(), *this); } /// \brief Begin iterator for edge set. - EdgeItr edgesBegin() { return edges.begin(); } + EdgeItr edgesBegin() const { return EdgeItr(0, *this); } /// \brief End iterator for edge set. - EdgeItr edgesEnd() { return edges.end(); } + EdgeItr edgesEnd() const { return EdgeItr(edges.size(), *this); } /// \brief Get begin iterator for adjacent edge set. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Begin iterator for the set of edges connected to the given node. - AdjEdgeItr adjEdgesBegin(NodeItr nItr) { - return getNode(nItr).edgesBegin(); + AdjEdgeItr adjEdgesBegin(NodeId nId) { + return getNode(nId).edgesBegin(); } /// \brief Get end iterator for adjacent edge set. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return End iterator for the set of edges connected to the given node. - AdjEdgeItr adjEdgesEnd(NodeItr nItr) { - return getNode(nItr).edgesEnd(); + AdjEdgeItr adjEdgesEnd(NodeId nId) { + return getNode(nId).edgesEnd(); } /// \brief Get the first node connected to this edge. - /// @param eItr Edge iterator. - /// @return The first node connected to the given edge. - NodeItr getEdgeNode1(EdgeItr eItr) { - return getEdge(eItr).getNode1(); + /// @param eId Edge id. + /// @return The first node connected to the given edge. + NodeId getEdgeNode1(EdgeId eId) { + return getEdge(eId).getNode1(); } /// \brief Get the second node connected to this edge. - /// @param eItr Edge iterator. - /// @return The second node connected to the given edge. - NodeItr getEdgeNode2(EdgeItr eItr) { - return getEdge(eItr).getNode2(); - } + /// @param eId Edge id. + /// @return The second node connected to the given edge. + NodeId getEdgeNode2(EdgeId eId) { + return getEdge(eId).getNode2(); + } /// \brief Get the "other" node connected to this edge. - /// @param eItr Edge iterator. - /// @param nItr Node iterator for the "given" node. - /// @return The iterator for the "other" node connected to this edge. - NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) { - EdgeEntry &e = getEdge(eItr); - if (e.getNode1() == nItr) { + /// @param eId Edge id. + /// @param nId Node id for the "given" node. + /// @return The iterator for the "other" node connected to this edge. + NodeId getEdgeOtherNode(EdgeId eId, NodeId nId) { + EdgeEntry &e = getEdge(eId); + if (e.getNode1() == nId) { return e.getNode2(); } // else return e.getNode1(); } + EdgeId invalidEdgeId() const { + return std::numeric_limits<EdgeId>::max(); + } + /// \brief Get the edge connecting two nodes. - /// @param n1Itr First node iterator. - /// @param n2Itr Second node iterator. - /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists, - /// otherwise returns edgesEnd(). - EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) { - for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr); + /// @param n1Id First node id. + /// @param n2Id Second node id. + /// @return An id for edge (n1Id, n2Id) if such an edge exists, + /// otherwise returns an invalid edge id. + EdgeId findEdge(NodeId n1Id, NodeId n2Id) { + for (AdjEdgeItr aeItr = adjEdgesBegin(n1Id), aeEnd = adjEdgesEnd(n1Id); aeItr != aeEnd; ++aeItr) { - if ((getEdgeNode1(*aeItr) == n2Itr) || - (getEdgeNode2(*aeItr) == n2Itr)) { + if ((getEdgeNode1(*aeItr) == n2Id) || + (getEdgeNode2(*aeItr) == n2Id)) { return *aeItr; } } - return edges.end(); + return invalidEdgeId(); } /// \brief Remove a node from the graph. - /// @param nItr Node iterator. - void removeNode(NodeItr nItr) { - NodeEntry &n = getNode(nItr); - for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) { - EdgeItr eItr = *itr; - ++itr; - removeEdge(eItr); + /// @param nId Node id. + void removeNode(NodeId nId) { + NodeEntry &n = getNode(nId); + for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end; ++itr) { + EdgeId eId = *itr; + removeEdge(eId); } - nodes.erase(nItr); - --numNodes; + freeNodes.push_back(nId); } /// \brief Remove an edge from the graph. - /// @param eItr Edge iterator. - void removeEdge(EdgeItr eItr) { - EdgeEntry &e = getEdge(eItr); + /// @param eId Edge id. + void removeEdge(EdgeId eId) { + EdgeEntry &e = getEdge(eId); NodeEntry &n1 = getNode(e.getNode1()); NodeEntry &n2 = getNode(e.getNode2()); n1.removeEdge(e.getNode1AEItr()); n2.removeEdge(e.getNode2AEItr()); - edges.erase(eItr); - --numEdges; + freeEdges.push_back(eId); } /// \brief Remove all nodes and edges from the graph. void clear() { nodes.clear(); + freeNodes.clear(); edges.clear(); - numNodes = numEdges = 0; + freeEdges.clear(); } /// \brief Dump a graph to an output stream. @@ -362,7 +397,7 @@ namespace PBQP { for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); nodeItr != nodeEnd; ++nodeItr) { - const Vector& v = getNodeCosts(nodeItr); + const Vector& v = getNodeCosts(*nodeItr); os << "\n" << v.getLength() << "\n"; assert(v.getLength() != 0 && "Empty vector in graph."); os << v[0]; @@ -374,10 +409,10 @@ namespace PBQP { for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); edgeItr != edgeEnd; ++edgeItr) { - unsigned n1 = std::distance(nodesBegin(), getEdgeNode1(edgeItr)); - unsigned n2 = std::distance(nodesBegin(), getEdgeNode2(edgeItr)); + NodeId n1 = getEdgeNode1(*edgeItr); + NodeId n2 = getEdgeNode2(*edgeItr); assert(n1 != n2 && "PBQP graphs shound not have self-edges."); - const Matrix& m = getEdgeCosts(edgeItr); + const Matrix& m = getEdgeCosts(*edgeItr); os << "\n" << n1 << " " << n2 << "\n" << m.getRows() << " " << m.getCols() << "\n"; assert(m.getRows() != 0 && "No rows in matrix."); @@ -396,14 +431,14 @@ namespace PBQP { /// @param os Output stream to print on. template <typename OStream> void printDot(OStream &os) { - + os << "graph {\n"; for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); nodeItr != nodeEnd; ++nodeItr) { os << " node" << nodeItr << " [ label=\"" - << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n"; + << nodeItr << ": " << getNodeCosts(*nodeItr) << "\" ]\n"; } os << " edge [ len=" << getNumNodes() << " ]\n"; @@ -411,11 +446,11 @@ namespace PBQP { for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); edgeItr != edgeEnd; ++edgeItr) { - os << " node" << getEdgeNode1(edgeItr) - << " -- node" << getEdgeNode2(edgeItr) + os << " node" << getEdgeNode1(*edgeItr) + << " -- node" << getEdgeNode2(*edgeItr) << " [ label=\""; - const Matrix &edgeCosts = getEdgeCosts(edgeItr); + const Matrix &edgeCosts = getEdgeCosts(*edgeItr); for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { os << edgeCosts.getRowAsVector(i) << "\\n"; @@ -427,39 +462,16 @@ namespace PBQP { }; - class NodeItrComparator { - public: - bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const { - return &*n1 < &*n2; - } - - bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const { - return &*n1 < &*n2; - } - }; - - class EdgeItrCompartor { - public: - bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const { - return &*e1 < &*e2; - } - - bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const { - return &*e1 < &*e2; - } - }; - - void Graph::copyFrom(const Graph &other) { - std::map<Graph::ConstNodeItr, Graph::NodeItr, - NodeItrComparator> nodeMap; +// void Graph::copyFrom(const Graph &other) { +// std::map<Graph::ConstNodeItr, Graph::NodeItr, +// NodeItrComparator> nodeMap; - for (Graph::ConstNodeItr nItr = other.nodesBegin(), - nEnd = other.nodesEnd(); - nItr != nEnd; ++nItr) { - nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); - } - - } +// for (Graph::ConstNodeItr nItr = other.nodesBegin(), +// nEnd = other.nodesEnd(); +// nItr != nEnd; ++nItr) { +// nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); +// } +// } } diff --git a/include/llvm/CodeGen/PBQP/HeuristicBase.h b/include/llvm/CodeGen/PBQP/HeuristicBase.h index 0c1fcb7..8bcbb9e 100644 --- a/include/llvm/CodeGen/PBQP/HeuristicBase.h +++ b/include/llvm/CodeGen/PBQP/HeuristicBase.h @@ -27,7 +27,7 @@ namespace PBQP { /// <li> void heuristicReduce() : Perform a single heuristic reduction. /// <li> void preUpdateEdgeCosts(Graph::EdgeItr) : Handle the (imminent) /// change to the cost matrix on the given edge (by R2). - /// <li> void postUpdateEdgeCostts(Graph::EdgeItr) : Handle the new + /// <li> void postUpdateEdgeCostts(Graph::EdgeItr) : Handle the new /// costs on the given edge. /// <li> void handleAddEdge(Graph::EdgeItr) : Handle the addition of a new /// edge into the PBQP graph (by R2). @@ -39,7 +39,7 @@ namespace PBQP { /// /// These methods are implemented in this class for documentation purposes, /// but will assert if called. - /// + /// /// Note that this class uses the curiously recursive template idiom to /// forward calls to the derived class. These methods need not be made /// virtual, and indeed probably shouldn't for performance reasons. @@ -52,7 +52,7 @@ namespace PBQP { class HeuristicBase { private: - typedef std::list<Graph::NodeItr> OptimalList; + typedef std::list<Graph::NodeId> OptimalList; HeuristicSolverImpl<HImpl> &s; Graph &g; @@ -62,9 +62,9 @@ namespace PBQP { HImpl& impl() { return static_cast<HImpl&>(*this); } // Add the given node to the optimal reductions list. Keep an iterator to - // its location for fast removal. - void addToOptimalReductionList(Graph::NodeItr nItr) { - optimalList.insert(optimalList.end(), nItr); + // its location for fast removal. + void addToOptimalReductionList(Graph::NodeId nId) { + optimalList.insert(optimalList.end(), nId); } public: @@ -94,7 +94,7 @@ namespace PBQP { /// behaviour. bool solverRunSimplify() const { return true; } - /// \brief Decide whether a node should be optimally or heuristically + /// \brief Decide whether a node should be optimally or heuristically /// reduced. /// @return Whether or not the given node should be listed for optimal /// reduction (via R0, R1 or R2). @@ -105,21 +105,21 @@ namespace PBQP { /// criteria. Note however that your criteria for selecting optimal nodes /// should be <i>at least</i> as strong as this. I.e. Nodes of degree 3 or /// higher should not be selected under any circumstances. - bool shouldOptimallyReduce(Graph::NodeItr nItr) { - if (g.getNodeDegree(nItr) < 3) + bool shouldOptimallyReduce(Graph::NodeId nId) { + if (g.getNodeDegree(nId) < 3) return true; // else return false; } /// \brief Add the given node to the list of nodes to be optimally reduced. - /// @param nItr Node iterator to be added. + /// @param nId Node id to be added. /// /// You probably don't want to over-ride this, except perhaps to record /// statistics before calling this implementation. HeuristicBase relies on /// its behaviour. - void addToOptimalReduceList(Graph::NodeItr nItr) { - optimalList.push_back(nItr); + void addToOptimalReduceList(Graph::NodeId nId) { + optimalList.push_back(nId); } /// \brief Initialise the heuristic. @@ -132,10 +132,10 @@ namespace PBQP { void setup() { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { - if (impl().shouldOptimallyReduce(nItr)) { - addToOptimalReduceList(nItr); + if (impl().shouldOptimallyReduce(*nItr)) { + addToOptimalReduceList(*nItr); } else { - impl().addToHeuristicReduceList(nItr); + impl().addToHeuristicReduceList(*nItr); } } } @@ -150,13 +150,13 @@ namespace PBQP { if (optimalList.empty()) return false; - Graph::NodeItr nItr = optimalList.front(); + Graph::NodeId nId = optimalList.front(); optimalList.pop_front(); - switch (s.getSolverDegree(nItr)) { - case 0: s.applyR0(nItr); break; - case 1: s.applyR1(nItr); break; - case 2: s.applyR2(nItr); break; + switch (s.getSolverDegree(nId)) { + case 0: s.applyR0(nId); break; + case 1: s.applyR1(nId); break; + case 2: s.applyR2(nId); break; default: llvm_unreachable( "Optimal reductions of degree > 2 nodes is invalid."); } @@ -184,8 +184,8 @@ namespace PBQP { } /// \brief Add a node to the heuristic reduce list. - /// @param nItr Node iterator to add to the heuristic reduce list. - void addToHeuristicList(Graph::NodeItr nItr) { + /// @param nId Node id to add to the heuristic reduce list. + void addToHeuristicList(Graph::NodeId nId) { llvm_unreachable("Must be implemented in derived class."); } @@ -199,31 +199,31 @@ namespace PBQP { } /// \brief Prepare a change in the costs on the given edge. - /// @param eItr Edge iterator. - void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void preUpdateEdgeCosts(Graph::EdgeId eId) { llvm_unreachable("Must be implemented in derived class."); } /// \brief Handle the change in the costs on the given edge. - /// @param eItr Edge iterator. - void postUpdateEdgeCostts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void postUpdateEdgeCostts(Graph::EdgeId eId) { llvm_unreachable("Must be implemented in derived class."); } /// \brief Handle the addition of a new edge into the PBQP graph. - /// @param eItr Edge iterator for the added edge. - void handleAddEdge(Graph::EdgeItr eItr) { + /// @param eId Edge id for the added edge. + void handleAddEdge(Graph::EdgeId eId) { llvm_unreachable("Must be implemented in derived class."); } /// \brief Handle disconnection of an edge from a node. - /// @param eItr Edge iterator for edge being disconnected. - /// @param nItr Node iterator for the node being disconnected from. + /// @param eId Edge id for edge being disconnected. + /// @param nId Node id for the node being disconnected from. /// /// Edges are frequently removed due to the removal of a node. This /// method allows for the effect to be computed only for the remaining /// node in the graph. - void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) { llvm_unreachable("Must be implemented in derived class."); } diff --git a/include/llvm/CodeGen/PBQP/HeuristicSolver.h b/include/llvm/CodeGen/PBQP/HeuristicSolver.h index 47e15b2..e26ca02 100644 --- a/include/llvm/CodeGen/PBQP/HeuristicSolver.h +++ b/include/llvm/CodeGen/PBQP/HeuristicSolver.h @@ -9,7 +9,7 @@ // // Heuristic PBQP solver. This solver is able to perform optimal reductions for // nodes of degree 0, 1 or 2. For nodes of degree >2 a plugable heuristic is -// used to select a node for reduction. +// used to select a node for reduction. // //===----------------------------------------------------------------------===// @@ -40,10 +40,10 @@ namespace PBQP { typedef typename HImpl::NodeData HeuristicNodeData; typedef typename HImpl::EdgeData HeuristicEdgeData; - typedef std::list<Graph::EdgeItr> SolverEdges; + typedef std::list<Graph::EdgeId> SolverEdges; public: - + /// \brief Iterator type for edges in the solver graph. typedef SolverEdges::iterator SolverEdgeItr; @@ -55,9 +55,9 @@ namespace PBQP { HeuristicNodeData& getHeuristicData() { return hData; } - SolverEdgeItr addSolverEdge(Graph::EdgeItr eItr) { + SolverEdgeItr addSolverEdge(Graph::EdgeId eId) { ++solverDegree; - return solverEdges.insert(solverEdges.end(), eItr); + return solverEdges.insert(solverEdges.end(), eId); } void removeSolverEdge(SolverEdgeItr seItr) { @@ -70,15 +70,15 @@ namespace PBQP { unsigned getSolverDegree() const { return solverDegree; } void clearSolverEdges() { solverDegree = 0; - solverEdges.clear(); + solverEdges.clear(); } - + private: HeuristicNodeData hData; unsigned solverDegree; SolverEdges solverEdges; }; - + class EdgeData { public: HeuristicEdgeData& getHeuristicData() { return hData; } @@ -104,7 +104,7 @@ namespace PBQP { Graph &g; HImpl h; Solution s; - std::vector<Graph::NodeItr> stack; + std::vector<Graph::NodeId> stack; typedef std::list<NodeData> NodeDataList; NodeDataList nodeDataList; @@ -117,7 +117,7 @@ namespace PBQP { /// \brief Construct a heuristic solver implementation to solve the given /// graph. /// @param g The graph representing the problem instance to be solved. - HeuristicSolverImpl(Graph &g) : g(g), h(*this) {} + HeuristicSolverImpl(Graph &g) : g(g), h(*this) {} /// \brief Get the graph being solved by this solver. /// @return The graph representing the problem instance being solved by this @@ -125,46 +125,46 @@ namespace PBQP { Graph& getGraph() { return g; } /// \brief Get the heuristic data attached to the given node. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return The heuristic data attached to the given node. - HeuristicNodeData& getHeuristicNodeData(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).getHeuristicData(); + HeuristicNodeData& getHeuristicNodeData(Graph::NodeId nId) { + return getSolverNodeData(nId).getHeuristicData(); } /// \brief Get the heuristic data attached to the given edge. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return The heuristic data attached to the given node. - HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { - return getSolverEdgeData(eItr).getHeuristicData(); + HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeId eId) { + return getSolverEdgeData(eId).getHeuristicData(); } /// \brief Begin iterator for the set of edges adjacent to the given node in /// the solver graph. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Begin iterator for the set of edges adjacent to the given node - /// in the solver graph. - SolverEdgeItr solverEdgesBegin(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).solverEdgesBegin(); + /// in the solver graph. + SolverEdgeItr solverEdgesBegin(Graph::NodeId nId) { + return getSolverNodeData(nId).solverEdgesBegin(); } /// \brief End iterator for the set of edges adjacent to the given node in /// the solver graph. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return End iterator for the set of edges adjacent to the given node in - /// the solver graph. - SolverEdgeItr solverEdgesEnd(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).solverEdgesEnd(); + /// the solver graph. + SolverEdgeItr solverEdgesEnd(Graph::NodeId nId) { + return getSolverNodeData(nId).solverEdgesEnd(); } /// \brief Remove a node from the solver graph. - /// @param eItr Edge iterator for edge to be removed. + /// @param eId Edge id for edge to be removed. /// /// Does <i>not</i> notify the heuristic of the removal. That should be /// done manually if necessary. - void removeSolverEdge(Graph::EdgeItr eItr) { - EdgeData &eData = getSolverEdgeData(eItr); - NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), - &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + void removeSolverEdge(Graph::EdgeId eId) { + EdgeData &eData = getSolverEdgeData(eId); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eId)); n1Data.removeSolverEdge(eData.getN1SolverEdgeItr()); n2Data.removeSolverEdge(eData.getN2SolverEdgeItr()); @@ -188,66 +188,66 @@ namespace PBQP { } /// \brief Add to the end of the stack. - /// @param nItr Node iterator to add to the reduction stack. - void pushToStack(Graph::NodeItr nItr) { - getSolverNodeData(nItr).clearSolverEdges(); - stack.push_back(nItr); + /// @param nId Node id to add to the reduction stack. + void pushToStack(Graph::NodeId nId) { + getSolverNodeData(nId).clearSolverEdges(); + stack.push_back(nId); } /// \brief Returns the solver degree of the given node. - /// @param nItr Node iterator for which degree is requested. + /// @param nId Node id for which degree is requested. /// @return Node degree in the <i>solver</i> graph (not the original graph). - unsigned getSolverDegree(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).getSolverDegree(); + unsigned getSolverDegree(Graph::NodeId nId) { + return getSolverNodeData(nId).getSolverDegree(); } /// \brief Set the solution of the given node. - /// @param nItr Node iterator to set solution for. + /// @param nId Node id to set solution for. /// @param selection Selection for node. - void setSolution(const Graph::NodeItr &nItr, unsigned selection) { - s.setSelection(nItr, selection); + void setSolution(const Graph::NodeId &nId, unsigned selection) { + s.setSelection(nId, selection); - for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), - aeEnd = g.adjEdgesEnd(nItr); + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId), + aeEnd = g.adjEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - Graph::EdgeItr eItr(*aeItr); - Graph::NodeItr anItr(g.getEdgeOtherNode(eItr, nItr)); - getSolverNodeData(anItr).addSolverEdge(eItr); + Graph::EdgeId eId(*aeItr); + Graph::NodeId anId(g.getEdgeOtherNode(eId, nId)); + getSolverNodeData(anId).addSolverEdge(eId); } } /// \brief Apply rule R0. - /// @param nItr Node iterator for node to apply R0 to. + /// @param nId Node id for node to apply R0 to. /// /// Node will be automatically pushed to the solver stack. - void applyR0(Graph::NodeItr nItr) { - assert(getSolverNodeData(nItr).getSolverDegree() == 0 && + void applyR0(Graph::NodeId nId) { + assert(getSolverNodeData(nId).getSolverDegree() == 0 && "R0 applied to node with degree != 0."); // Nothing to do. Just push the node onto the reduction stack. - pushToStack(nItr); + pushToStack(nId); s.recordR0(); } /// \brief Apply rule R1. - /// @param xnItr Node iterator for node to apply R1 to. + /// @param xnId Node id for node to apply R1 to. /// /// Node will be automatically pushed to the solver stack. - void applyR1(Graph::NodeItr xnItr) { - NodeData &nd = getSolverNodeData(xnItr); + void applyR1(Graph::NodeId xnId) { + NodeData &nd = getSolverNodeData(xnId); assert(nd.getSolverDegree() == 1 && "R1 applied to node with degree != 1."); - Graph::EdgeItr eItr = *nd.solverEdgesBegin(); + Graph::EdgeId eId = *nd.solverEdgesBegin(); + + const Matrix &eCosts = g.getEdgeCosts(eId); + const Vector &xCosts = g.getNodeCosts(xnId); - const Matrix &eCosts = g.getEdgeCosts(eItr); - const Vector &xCosts = g.getNodeCosts(xnItr); - // Duplicate a little to avoid transposing matrices. - if (xnItr == g.getEdgeNode1(eItr)) { - Graph::NodeItr ynItr = g.getEdgeNode2(eItr); - Vector &yCosts = g.getNodeCosts(ynItr); + if (xnId == g.getEdgeNode1(eId)) { + Graph::NodeId ynId = g.getEdgeNode2(eId); + Vector &yCosts = g.getNodeCosts(ynId); for (unsigned j = 0; j < yCosts.getLength(); ++j) { PBQPNum min = eCosts[0][j] + xCosts[0]; for (unsigned i = 1; i < xCosts.getLength(); ++i) { @@ -257,10 +257,10 @@ namespace PBQP { } yCosts[j] += min; } - h.handleRemoveEdge(eItr, ynItr); + h.handleRemoveEdge(eId, ynId); } else { - Graph::NodeItr ynItr = g.getEdgeNode1(eItr); - Vector &yCosts = g.getNodeCosts(ynItr); + Graph::NodeId ynId = g.getEdgeNode1(eId); + Vector &yCosts = g.getNodeCosts(ynId); for (unsigned i = 0; i < yCosts.getLength(); ++i) { PBQPNum min = eCosts[i][0] + xCosts[0]; for (unsigned j = 1; j < xCosts.getLength(); ++j) { @@ -270,48 +270,48 @@ namespace PBQP { } yCosts[i] += min; } - h.handleRemoveEdge(eItr, ynItr); + h.handleRemoveEdge(eId, ynId); } - removeSolverEdge(eItr); + removeSolverEdge(eId); assert(nd.getSolverDegree() == 0 && "Degree 1 with edge removed should be 0."); - pushToStack(xnItr); + pushToStack(xnId); s.recordR1(); } /// \brief Apply rule R2. - /// @param xnItr Node iterator for node to apply R2 to. + /// @param xnId Node id for node to apply R2 to. /// /// Node will be automatically pushed to the solver stack. - void applyR2(Graph::NodeItr xnItr) { - assert(getSolverNodeData(xnItr).getSolverDegree() == 2 && + void applyR2(Graph::NodeId xnId) { + assert(getSolverNodeData(xnId).getSolverDegree() == 2 && "R2 applied to node with degree != 2."); - NodeData &nd = getSolverNodeData(xnItr); - const Vector &xCosts = g.getNodeCosts(xnItr); + NodeData &nd = getSolverNodeData(xnId); + const Vector &xCosts = g.getNodeCosts(xnId); SolverEdgeItr aeItr = nd.solverEdgesBegin(); - Graph::EdgeItr yxeItr = *aeItr, - zxeItr = *(++aeItr); + Graph::EdgeId yxeId = *aeItr, + zxeId = *(++aeItr); - Graph::NodeItr ynItr = g.getEdgeOtherNode(yxeItr, xnItr), - znItr = g.getEdgeOtherNode(zxeItr, xnItr); + Graph::NodeId ynId = g.getEdgeOtherNode(yxeId, xnId), + znId = g.getEdgeOtherNode(zxeId, xnId); - bool flipEdge1 = (g.getEdgeNode1(yxeItr) == xnItr), - flipEdge2 = (g.getEdgeNode1(zxeItr) == xnItr); + bool flipEdge1 = (g.getEdgeNode1(yxeId) == xnId), + flipEdge2 = (g.getEdgeNode1(zxeId) == xnId); const Matrix *yxeCosts = flipEdge1 ? - new Matrix(g.getEdgeCosts(yxeItr).transpose()) : - &g.getEdgeCosts(yxeItr); + new Matrix(g.getEdgeCosts(yxeId).transpose()) : + &g.getEdgeCosts(yxeId); const Matrix *zxeCosts = flipEdge2 ? - new Matrix(g.getEdgeCosts(zxeItr).transpose()) : - &g.getEdgeCosts(zxeItr); + new Matrix(g.getEdgeCosts(zxeId).transpose()) : + &g.getEdgeCosts(zxeId); unsigned xLen = xCosts.getLength(), yLen = yxeCosts->getRows(), zLen = zxeCosts->getRows(); - + Matrix delta(yLen, zLen); for (unsigned i = 0; i < yLen; ++i) { @@ -333,79 +333,79 @@ namespace PBQP { if (flipEdge2) delete zxeCosts; - Graph::EdgeItr yzeItr = g.findEdge(ynItr, znItr); + Graph::EdgeId yzeId = g.findEdge(ynId, znId); bool addedEdge = false; - if (yzeItr == g.edgesEnd()) { - yzeItr = g.addEdge(ynItr, znItr, delta); + if (yzeId == g.invalidEdgeId()) { + yzeId = g.addEdge(ynId, znId, delta); addedEdge = true; } else { - Matrix &yzeCosts = g.getEdgeCosts(yzeItr); - h.preUpdateEdgeCosts(yzeItr); - if (ynItr == g.getEdgeNode1(yzeItr)) { + Matrix &yzeCosts = g.getEdgeCosts(yzeId); + h.preUpdateEdgeCosts(yzeId); + if (ynId == g.getEdgeNode1(yzeId)) { yzeCosts += delta; } else { yzeCosts += delta.transpose(); } } - bool nullCostEdge = tryNormaliseEdgeMatrix(yzeItr); + bool nullCostEdge = tryNormaliseEdgeMatrix(yzeId); if (!addedEdge) { // If we modified the edge costs let the heuristic know. - h.postUpdateEdgeCosts(yzeItr); + h.postUpdateEdgeCosts(yzeId); } - + if (nullCostEdge) { // If this edge ended up null remove it. if (!addedEdge) { // We didn't just add it, so we need to notify the heuristic // and remove it from the solver. - h.handleRemoveEdge(yzeItr, ynItr); - h.handleRemoveEdge(yzeItr, znItr); - removeSolverEdge(yzeItr); + h.handleRemoveEdge(yzeId, ynId); + h.handleRemoveEdge(yzeId, znId); + removeSolverEdge(yzeId); } - g.removeEdge(yzeItr); + g.removeEdge(yzeId); } else if (addedEdge) { // If the edge was added, and non-null, finish setting it up, add it to // the solver & notify heuristic. edgeDataList.push_back(EdgeData()); - g.setEdgeData(yzeItr, &edgeDataList.back()); - addSolverEdge(yzeItr); - h.handleAddEdge(yzeItr); + g.setEdgeData(yzeId, &edgeDataList.back()); + addSolverEdge(yzeId); + h.handleAddEdge(yzeId); } - h.handleRemoveEdge(yxeItr, ynItr); - removeSolverEdge(yxeItr); - h.handleRemoveEdge(zxeItr, znItr); - removeSolverEdge(zxeItr); + h.handleRemoveEdge(yxeId, ynId); + removeSolverEdge(yxeId); + h.handleRemoveEdge(zxeId, znId); + removeSolverEdge(zxeId); - pushToStack(xnItr); + pushToStack(xnId); s.recordR2(); } /// \brief Record an application of the RN rule. /// /// For use by the HeuristicBase. - void recordRN() { s.recordRN(); } + void recordRN() { s.recordRN(); } private: - NodeData& getSolverNodeData(Graph::NodeItr nItr) { - return *static_cast<NodeData*>(g.getNodeData(nItr)); + NodeData& getSolverNodeData(Graph::NodeId nId) { + return *static_cast<NodeData*>(g.getNodeData(nId)); } - EdgeData& getSolverEdgeData(Graph::EdgeItr eItr) { - return *static_cast<EdgeData*>(g.getEdgeData(eItr)); + EdgeData& getSolverEdgeData(Graph::EdgeId eId) { + return *static_cast<EdgeData*>(g.getEdgeData(eId)); } - void addSolverEdge(Graph::EdgeItr eItr) { - EdgeData &eData = getSolverEdgeData(eItr); - NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), - &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + void addSolverEdge(Graph::EdgeId eId) { + EdgeData &eData = getSolverEdgeData(eId); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eId)); - eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eItr)); - eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eItr)); + eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eId)); + eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eId)); } void setup() { @@ -417,15 +417,15 @@ namespace PBQP { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { nodeDataList.push_back(NodeData()); - g.setNodeData(nItr, &nodeDataList.back()); + g.setNodeData(*nItr, &nodeDataList.back()); } // Create edge data objects. for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); eItr != eEnd; ++eItr) { edgeDataList.push_back(EdgeData()); - g.setEdgeData(eItr, &edgeDataList.back()); - addSolverEdge(eItr); + g.setEdgeData(*eItr, &edgeDataList.back()); + addSolverEdge(*eItr); } } @@ -441,28 +441,30 @@ namespace PBQP { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { - if (g.getNodeCosts(nItr).getLength() == 1) { + Graph::NodeId nId = *nItr; + + if (g.getNodeCosts(nId).getLength() == 1) { - std::vector<Graph::EdgeItr> edgesToRemove; + std::vector<Graph::EdgeId> edgesToRemove; - for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), - aeEnd = g.adjEdgesEnd(nItr); + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId), + aeEnd = g.adjEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - Graph::EdgeItr eItr = *aeItr; + Graph::EdgeId eId = *aeItr; - if (g.getEdgeNode1(eItr) == nItr) { - Graph::NodeItr otherNodeItr = g.getEdgeNode2(eItr); - g.getNodeCosts(otherNodeItr) += - g.getEdgeCosts(eItr).getRowAsVector(0); + if (g.getEdgeNode1(eId) == nId) { + Graph::NodeId otherNodeId = g.getEdgeNode2(eId); + g.getNodeCosts(otherNodeId) += + g.getEdgeCosts(eId).getRowAsVector(0); } else { - Graph::NodeItr otherNodeItr = g.getEdgeNode1(eItr); - g.getNodeCosts(otherNodeItr) += - g.getEdgeCosts(eItr).getColAsVector(0); + Graph::NodeId otherNodeId = g.getEdgeNode1(eId); + g.getNodeCosts(otherNodeId) += + g.getEdgeCosts(eId).getColAsVector(0); } - edgesToRemove.push_back(eItr); + edgesToRemove.push_back(eId); } if (!edgesToRemove.empty()) @@ -477,12 +479,12 @@ namespace PBQP { } void eliminateIndependentEdges() { - std::vector<Graph::EdgeItr> edgesToProcess; + std::vector<Graph::EdgeId> edgesToProcess; unsigned numEliminated = 0; for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); eItr != eEnd; ++eItr) { - edgesToProcess.push_back(eItr); + edgesToProcess.push_back(*eItr); } while (!edgesToProcess.empty()) { @@ -492,21 +494,21 @@ namespace PBQP { } } - bool tryToEliminateEdge(Graph::EdgeItr eItr) { - if (tryNormaliseEdgeMatrix(eItr)) { - g.removeEdge(eItr); - return true; + bool tryToEliminateEdge(Graph::EdgeId eId) { + if (tryNormaliseEdgeMatrix(eId)) { + g.removeEdge(eId); + return true; } return false; } - bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) { + bool tryNormaliseEdgeMatrix(Graph::EdgeId &eId) { const PBQPNum infinity = std::numeric_limits<PBQPNum>::infinity(); - Matrix &edgeCosts = g.getEdgeCosts(eItr); - Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eItr)), - &vCosts = g.getNodeCosts(g.getEdgeNode2(eItr)); + Matrix &edgeCosts = g.getEdgeCosts(eId); + Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eId)), + &vCosts = g.getNodeCosts(g.getEdgeNode2(eId)); for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { PBQPNum rowMin = infinity; @@ -554,34 +556,34 @@ namespace PBQP { } } - void computeSolution(Graph::NodeItr nItr) { + void computeSolution(Graph::NodeId nId) { - NodeData &nodeData = getSolverNodeData(nItr); + NodeData &nodeData = getSolverNodeData(nId); - Vector v(g.getNodeCosts(nItr)); + Vector v(g.getNodeCosts(nId)); // Solve based on existing solved edges. for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(), solvedEdgeEnd = nodeData.solverEdgesEnd(); solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) { - Graph::EdgeItr eItr(*solvedEdgeItr); - Matrix &edgeCosts = g.getEdgeCosts(eItr); + Graph::EdgeId eId(*solvedEdgeItr); + Matrix &edgeCosts = g.getEdgeCosts(eId); - if (nItr == g.getEdgeNode1(eItr)) { - Graph::NodeItr adjNode(g.getEdgeNode2(eItr)); + if (nId == g.getEdgeNode1(eId)) { + Graph::NodeId adjNode(g.getEdgeNode2(eId)); unsigned adjSolution = s.getSelection(adjNode); v += edgeCosts.getColAsVector(adjSolution); } else { - Graph::NodeItr adjNode(g.getEdgeNode1(eItr)); + Graph::NodeId adjNode(g.getEdgeNode1(eId)); unsigned adjSolution = s.getSelection(adjNode); v += edgeCosts.getRowAsVector(adjSolution); } } - setSolution(nItr, v.minIndex()); + setSolution(nId, v.minIndex()); } void cleanup() { diff --git a/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h b/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h index 307d81e..c355c2c 100644 --- a/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h +++ b/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h @@ -27,7 +27,7 @@ namespace PBQP { /// \brief PBQP Heuristic which applies an allocability test based on /// Briggs. - /// + /// /// This heuristic assumes that the elements of cost vectors in the PBQP /// problem represent storage options, with the first being the spill /// option and subsequent elements representing legal registers for the @@ -39,16 +39,16 @@ namespace PBQP { /// solver stack. If no nodes can be proven allocable then the node with /// the lowest estimated spill cost is selected and push to the solver stack /// instead. - /// - /// This implementation is built on top of HeuristicBase. + /// + /// This implementation is built on top of HeuristicBase. class Briggs : public HeuristicBase<Briggs> { private: class LinkDegreeComparator { public: LinkDegreeComparator(HeuristicSolverImpl<Briggs> &s) : s(&s) {} - bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { - if (s->getSolverDegree(n1Itr) > s->getSolverDegree(n2Itr)) + bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const { + if (s->getSolverDegree(n1Id) > s->getSolverDegree(n2Id)) return true; return false; } @@ -60,12 +60,12 @@ namespace PBQP { public: SpillCostComparator(HeuristicSolverImpl<Briggs> &s) : s(&s), g(&s.getGraph()) {} - bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { - const PBQP::Vector &cv1 = g->getNodeCosts(n1Itr); - const PBQP::Vector &cv2 = g->getNodeCosts(n2Itr); + bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const { + const PBQP::Vector &cv1 = g->getNodeCosts(n1Id); + const PBQP::Vector &cv2 = g->getNodeCosts(n2Id); - PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Itr); - PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Itr); + PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Id); + PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Id); if (cost1 < cost2) return true; @@ -77,10 +77,10 @@ namespace PBQP { Graph *g; }; - typedef std::list<Graph::NodeItr> RNAllocableList; + typedef std::list<Graph::NodeId> RNAllocableList; typedef RNAllocableList::iterator RNAllocableListItr; - typedef std::list<Graph::NodeItr> RNUnallocableList; + typedef std::list<Graph::NodeId> RNUnallocableList; typedef RNUnallocableList::iterator RNUnallocableListItr; public: @@ -114,7 +114,7 @@ namespace PBQP { /// \brief Determine whether a node should be reduced using optimal /// reduction. - /// @param nItr Node iterator to be considered. + /// @param nId Node id to be considered. /// @return True if the given node should be optimally reduced, false /// otherwise. /// @@ -123,8 +123,8 @@ namespace PBQP { /// infinite are checked for allocability first. Allocable nodes may be /// optimally reduced, but nodes whose allocability cannot be proven are /// selected for heuristic reduction instead. - bool shouldOptimallyReduce(Graph::NodeItr nItr) { - if (getSolver().getSolverDegree(nItr) < 3) { + bool shouldOptimallyReduce(Graph::NodeId nId) { + if (getSolver().getSolverDegree(nId) < 3) { return true; } // else @@ -132,15 +132,15 @@ namespace PBQP { } /// \brief Add a node to the heuristic reduce list. - /// @param nItr Node iterator to add to the heuristic reduce list. - void addToHeuristicReduceList(Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); - initializeNode(nItr); + /// @param nId Node id to add to the heuristic reduce list. + void addToHeuristicReduceList(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); + initializeNode(nId); nd.isHeuristic = true; if (nd.isAllocable) { - nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId); } else { - nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nItr); + nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nId); } } @@ -159,19 +159,19 @@ namespace PBQP { RNAllocableListItr rnaItr = min_element(rnAllocableList.begin(), rnAllocableList.end(), LinkDegreeComparator(getSolver())); - Graph::NodeItr nItr = *rnaItr; + Graph::NodeId nId = *rnaItr; rnAllocableList.erase(rnaItr); - handleRemoveNode(nItr); - getSolver().pushToStack(nItr); + handleRemoveNode(nId); + getSolver().pushToStack(nId); return true; } else if (!rnUnallocableList.empty()) { RNUnallocableListItr rnuItr = min_element(rnUnallocableList.begin(), rnUnallocableList.end(), SpillCostComparator(getSolver())); - Graph::NodeItr nItr = *rnuItr; + Graph::NodeId nId = *rnuItr; rnUnallocableList.erase(rnuItr); - handleRemoveNode(nItr); - getSolver().pushToStack(nItr); + handleRemoveNode(nId); + getSolver().pushToStack(nId); return true; } // else @@ -179,43 +179,43 @@ namespace PBQP { } /// \brief Prepare a change in the costs on the given edge. - /// @param eItr Edge iterator. - void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void preUpdateEdgeCosts(Graph::EdgeId eId) { Graph &g = getGraph(); - Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), - n2Itr = g.getEdgeNode2(eItr); - NodeData &n1 = getHeuristicNodeData(n1Itr), - &n2 = getHeuristicNodeData(n2Itr); + Graph::NodeId n1Id = g.getEdgeNode1(eId), + n2Id = g.getEdgeNode2(eId); + NodeData &n1 = getHeuristicNodeData(n1Id), + &n2 = getHeuristicNodeData(n2Id); if (n1.isHeuristic) - subtractEdgeContributions(eItr, getGraph().getEdgeNode1(eItr)); + subtractEdgeContributions(eId, getGraph().getEdgeNode1(eId)); if (n2.isHeuristic) - subtractEdgeContributions(eItr, getGraph().getEdgeNode2(eItr)); + subtractEdgeContributions(eId, getGraph().getEdgeNode2(eId)); - EdgeData &ed = getHeuristicEdgeData(eItr); + EdgeData &ed = getHeuristicEdgeData(eId); ed.isUpToDate = false; } /// \brief Handle the change in the costs on the given edge. - /// @param eItr Edge iterator. - void postUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void postUpdateEdgeCosts(Graph::EdgeId eId) { // This is effectively the same as adding a new edge now, since // we've factored out the costs of the old one. - handleAddEdge(eItr); + handleAddEdge(eId); } /// \brief Handle the addition of a new edge into the PBQP graph. - /// @param eItr Edge iterator for the added edge. + /// @param eId Edge id for the added edge. /// /// Updates allocability of any nodes connected by this edge which are /// being managed by the heuristic. If allocability changes they are /// moved to the appropriate list. - void handleAddEdge(Graph::EdgeItr eItr) { + void handleAddEdge(Graph::EdgeId eId) { Graph &g = getGraph(); - Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), - n2Itr = g.getEdgeNode2(eItr); - NodeData &n1 = getHeuristicNodeData(n1Itr), - &n2 = getHeuristicNodeData(n2Itr); + Graph::NodeId n1Id = g.getEdgeNode1(eId), + n2Id = g.getEdgeNode2(eId); + NodeData &n1 = getHeuristicNodeData(n1Id), + &n2 = getHeuristicNodeData(n2Id); // If neither node is managed by the heuristic there's nothing to be // done. @@ -223,60 +223,60 @@ namespace PBQP { return; // Ok - we need to update at least one node. - computeEdgeContributions(eItr); + computeEdgeContributions(eId); // Update node 1 if it's managed by the heuristic. if (n1.isHeuristic) { bool n1WasAllocable = n1.isAllocable; - addEdgeContributions(eItr, n1Itr); - updateAllocability(n1Itr); + addEdgeContributions(eId, n1Id); + updateAllocability(n1Id); if (n1WasAllocable && !n1.isAllocable) { rnAllocableList.erase(n1.rnaItr); n1.rnuItr = - rnUnallocableList.insert(rnUnallocableList.end(), n1Itr); + rnUnallocableList.insert(rnUnallocableList.end(), n1Id); } } // Likewise for node 2. if (n2.isHeuristic) { bool n2WasAllocable = n2.isAllocable; - addEdgeContributions(eItr, n2Itr); - updateAllocability(n2Itr); + addEdgeContributions(eId, n2Id); + updateAllocability(n2Id); if (n2WasAllocable && !n2.isAllocable) { rnAllocableList.erase(n2.rnaItr); n2.rnuItr = - rnUnallocableList.insert(rnUnallocableList.end(), n2Itr); + rnUnallocableList.insert(rnUnallocableList.end(), n2Id); } } } /// \brief Handle disconnection of an edge from a node. - /// @param eItr Edge iterator for edge being disconnected. - /// @param nItr Node iterator for the node being disconnected from. + /// @param eId Edge id for edge being disconnected. + /// @param nId Node id for the node being disconnected from. /// /// Updates allocability of the given node and, if appropriate, moves the /// node to a new list. - void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); + void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) { + NodeData &nd =getHeuristicNodeData(nId); // If the node is not managed by the heuristic there's nothing to be // done. if (!nd.isHeuristic) return; - EdgeData &ed = getHeuristicEdgeData(eItr); + EdgeData &ed = getHeuristicEdgeData(eId); (void)ed; assert(ed.isUpToDate && "Edge data is not up to date."); // Update node. bool ndWasAllocable = nd.isAllocable; - subtractEdgeContributions(eItr, nItr); - updateAllocability(nItr); + subtractEdgeContributions(eId, nId); + updateAllocability(nId); // If the node has gone optimal... - if (shouldOptimallyReduce(nItr)) { + if (shouldOptimallyReduce(nId)) { nd.isHeuristic = false; - addToOptimalReduceList(nItr); + addToOptimalReduceList(nId); if (ndWasAllocable) { rnAllocableList.erase(nd.rnaItr); } else { @@ -287,36 +287,36 @@ namespace PBQP { // from "unallocable" to "allocable". if (!ndWasAllocable && nd.isAllocable) { rnUnallocableList.erase(nd.rnuItr); - nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId); } } } private: - NodeData& getHeuristicNodeData(Graph::NodeItr nItr) { - return getSolver().getHeuristicNodeData(nItr); + NodeData& getHeuristicNodeData(Graph::NodeId nId) { + return getSolver().getHeuristicNodeData(nId); } - EdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { - return getSolver().getHeuristicEdgeData(eItr); + EdgeData& getHeuristicEdgeData(Graph::EdgeId eId) { + return getSolver().getHeuristicEdgeData(eId); } // Work out what this edge will contribute to the allocability of the // nodes connected to it. - void computeEdgeContributions(Graph::EdgeItr eItr) { - EdgeData &ed = getHeuristicEdgeData(eItr); + void computeEdgeContributions(Graph::EdgeId eId) { + EdgeData &ed = getHeuristicEdgeData(eId); if (ed.isUpToDate) return; // Edge data is already up to date. - Matrix &eCosts = getGraph().getEdgeCosts(eItr); + Matrix &eCosts = getGraph().getEdgeCosts(eId); unsigned numRegs = eCosts.getRows() - 1, numReverseRegs = eCosts.getCols() - 1; std::vector<unsigned> rowInfCounts(numRegs, 0), - colInfCounts(numReverseRegs, 0); + colInfCounts(numReverseRegs, 0); ed.worst = 0; ed.reverseWorst = 0; @@ -348,19 +348,19 @@ namespace PBQP { ed.isUpToDate = true; } - // Add the contributions of the given edge to the given node's + // Add the contributions of the given edge to the given node's // numDenied and safe members. No action is taken other than to update // these member values. Once updated these numbers can be used by clients // to update the node's allocability. - void addEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { - EdgeData &ed = getHeuristicEdgeData(eItr); + void addEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) { + EdgeData &ed = getHeuristicEdgeData(eId); assert(ed.isUpToDate && "Using out-of-date edge numbers."); - NodeData &nd = getHeuristicNodeData(nItr); - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; - - bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; + + bool nIsNode1 = nId == getGraph().getEdgeNode1(eId); EdgeData::UnsafeArray &unsafe = nIsNode1 ? ed.unsafe : ed.reverseUnsafe; nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst; @@ -375,25 +375,25 @@ namespace PBQP { } } - // Subtract the contributions of the given edge to the given node's + // Subtract the contributions of the given edge to the given node's // numDenied and safe members. No action is taken other than to update // these member values. Once updated these numbers can be used by clients // to update the node's allocability. - void subtractEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { - EdgeData &ed = getHeuristicEdgeData(eItr); + void subtractEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) { + EdgeData &ed = getHeuristicEdgeData(eId); assert(ed.isUpToDate && "Using out-of-date edge numbers."); - NodeData &nd = getHeuristicNodeData(nItr); - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; - - bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; + + bool nIsNode1 = nId == getGraph().getEdgeNode1(eId); EdgeData::UnsafeArray &unsafe = nIsNode1 ? ed.unsafe : ed.reverseUnsafe; nd.numDenied -= nIsNode1 ? ed.worst : ed.reverseWorst; for (unsigned r = 0; r < numRegs; ++r) { - if (unsafe[r]) { + if (unsafe[r]) { if (nd.unsafeDegrees[r] == 1) { ++nd.numSafe; } @@ -402,22 +402,22 @@ namespace PBQP { } } - void updateAllocability(Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + void updateAllocability(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0; } - void initializeNode(Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); + void initializeNode(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); if (nd.isInitialized) return; // Node data is already up to date. - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; nd.numDenied = 0; - const Vector& nCosts = getGraph().getNodeCosts(nItr); + const Vector& nCosts = getGraph().getNodeCosts(nId); for (unsigned i = 1; i < nCosts.getLength(); ++i) { if (nCosts[i] == std::numeric_limits<PBQPNum>::infinity()) ++nd.numDenied; @@ -428,27 +428,27 @@ namespace PBQP { typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr; - for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nItr), - aeEnd = getSolver().solverEdgesEnd(nItr); + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nId), + aeEnd = getSolver().solverEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - - Graph::EdgeItr eItr = *aeItr; - computeEdgeContributions(eItr); - addEdgeContributions(eItr, nItr); + + Graph::EdgeId eId = *aeItr; + computeEdgeContributions(eId); + addEdgeContributions(eId, nId); } - updateAllocability(nItr); + updateAllocability(nId); nd.isInitialized = true; } - void handleRemoveNode(Graph::NodeItr xnItr) { + void handleRemoveNode(Graph::NodeId xnId) { typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr; - std::vector<Graph::EdgeItr> edgesToRemove; - for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnItr), - aeEnd = getSolver().solverEdgesEnd(xnItr); + std::vector<Graph::EdgeId> edgesToRemove; + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnId), + aeEnd = getSolver().solverEdgesEnd(xnId); aeItr != aeEnd; ++aeItr) { - Graph::NodeItr ynItr = getGraph().getEdgeOtherNode(*aeItr, xnItr); - handleRemoveEdge(*aeItr, ynItr); + Graph::NodeId ynId = getGraph().getEdgeOtherNode(*aeItr, xnId); + handleRemoveEdge(*aeItr, ynId); edgesToRemove.push_back(*aeItr); } while (!edgesToRemove.empty()) { diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index b9f288b..091805d 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -26,8 +26,7 @@ namespace PBQP { class Solution { private: - typedef std::map<Graph::ConstNodeItr, unsigned, - NodeItrComparator> SelectionsMap; + typedef std::map<Graph::NodeId, unsigned> SelectionsMap; SelectionsMap selections; unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions; @@ -71,17 +70,17 @@ namespace PBQP { unsigned numRNReductions() const { return rNReductions; } /// \brief Set the selection for a given node. - /// @param nItr Node iterator. - /// @param selection Selection for nItr. - void setSelection(Graph::NodeItr nItr, unsigned selection) { - selections[nItr] = selection; + /// @param nodeId Node id. + /// @param selection Selection for nodeId. + void setSelection(Graph::NodeId nodeId, unsigned selection) { + selections[nodeId] = selection; } /// \brief Get a node's selection. - /// @param nItr Node iterator. - /// @return The selection for nItr; - unsigned getSelection(Graph::ConstNodeItr nItr) const { - SelectionsMap::const_iterator sItr = selections.find(nItr); + /// @param nodeId Node id. + /// @return The selection for nodeId; + unsigned getSelection(Graph::NodeId nodeId) const { + SelectionsMap::const_iterator sItr = selections.find(nodeId); assert(sItr != selections.end() && "No selection for node."); return sItr->second; } diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 9b6f61e..ae4a2fa 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -21,19 +21,22 @@ namespace llvm { - class FunctionPass; - class MachineFunctionPass; - class PassInfo; - class PassManagerBase; - class TargetLoweringBase; - class TargetLowering; - class TargetRegisterClass; - class raw_ostream; -} - -namespace llvm { - +class FunctionPass; +class MachineFunctionPass; class PassConfigImpl; +class PassInfo; +class ScheduleDAGInstrs; +class TargetLowering; +class TargetLoweringBase; +class TargetRegisterClass; +class raw_ostream; +struct MachineSchedContext; + +// The old pass manager infrastructure is hidden in a legacy namespace now. +namespace legacy { +class PassManagerBase; +} +using legacy::PassManagerBase; /// Discriminated union of Pass ID types. /// @@ -204,6 +207,20 @@ public: /// Fully developed targets will not generally override this. virtual void addMachinePasses(); + /// createTargetScheduler - Create an instance of ScheduleDAGInstrs to be run + /// within the standard MachineScheduler pass for this function and target at + /// the current optimization level. + /// + /// This can also be used to plug a new MachineSchedStrategy into an instance + /// of the standard ScheduleDAGMI: + /// return new ScheduleDAGMI(C, new MyStrategy(C)) + /// + /// Return NULL to select the default (generic) machine scheduler. + virtual ScheduleDAGInstrs * + createMachineScheduler(MachineSchedContext *C) const { + return 0; + } + protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); @@ -365,14 +382,6 @@ namespace llvm { /// these register allocator like this: AU.addRequiredID(PHIEliminationID); extern char &PHIEliminationID; - /// StrongPHIElimination - This pass eliminates machine instruction PHI - /// nodes by inserting copy instructions. This destroys SSA information, but - /// is the desired input for some register allocators. This pass is - /// "required" by these register allocator like this: - /// AU.addRequiredID(PHIEliminationID); - /// This pass is still in development - extern char &StrongPHIEliminationID; - /// LiveIntervals - This analysis keeps track of the live ranges of virtual /// and physical registers. extern char &LiveIntervalsID; diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index df74d088..705086c 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -44,7 +44,7 @@ namespace llvm { virtual bool isAliased(const MachineFrameInfo *) const; /// mayAlias - Return true if the memory pointed to by this - /// PseudoSourceValue can ever alias a LLVM IR Value. + /// PseudoSourceValue can ever alias an LLVM IR Value. virtual bool mayAlias(const MachineFrameInfo *) const; /// classof - Methods for support type inquiry through isa, cast, and diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 6f2d139..7472e5a 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -52,22 +52,22 @@ namespace llvm { /// PBQPBuilder you are unlikely to need this: Nodes and options for all /// vregs will already have been set up for you by the base class. template <typename AllowedRegsItr> - void recordVReg(unsigned vreg, PBQP::Graph::NodeItr node, + void recordVReg(unsigned vreg, PBQP::Graph::NodeId nodeId, AllowedRegsItr arBegin, AllowedRegsItr arEnd) { - assert(node2VReg.find(node) == node2VReg.end() && "Re-mapping node."); + assert(node2VReg.find(nodeId) == node2VReg.end() && "Re-mapping node."); assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg."); assert(allowedSets[vreg].empty() && "vreg already has pregs."); - node2VReg[node] = vreg; - vreg2Node[vreg] = node; + node2VReg[nodeId] = vreg; + vreg2Node[vreg] = nodeId; std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg])); } /// Get the virtual register corresponding to the given PBQP node. - unsigned getVRegForNode(PBQP::Graph::ConstNodeItr node) const; + unsigned getVRegForNode(PBQP::Graph::NodeId nodeId) const; /// Get the PBQP node corresponding to the given virtual register. - PBQP::Graph::NodeItr getNodeForVReg(unsigned vreg) const; + PBQP::Graph::NodeId getNodeForVReg(unsigned vreg) const; /// Returns true if the given PBQP option represents a physical register, /// false otherwise. @@ -92,9 +92,8 @@ namespace llvm { private: - typedef std::map<PBQP::Graph::ConstNodeItr, unsigned, - PBQP::NodeItrComparator> Node2VReg; - typedef DenseMap<unsigned, PBQP::Graph::NodeItr> VReg2Node; + typedef std::map<PBQP::Graph::NodeId, unsigned> Node2VReg; + typedef DenseMap<unsigned, PBQP::Graph::NodeId> VReg2Node; typedef DenseMap<unsigned, AllowedSet> AllowedSetMap; PBQP::Graph graph; diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index 8a0a8f3..a801d1d 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -22,7 +22,7 @@ namespace llvm { class LiveIntervals; -class LiveInterval; +class LiveRange; class RegisterClassInfo; class MachineInstr; @@ -89,20 +89,89 @@ struct RegionPressure : RegisterPressure { void openBottom(MachineBasicBlock::const_iterator PrevBottom); }; -/// An element of pressure difference that identifies the pressure set and -/// amount of increase or decrease in units of pressure. -struct PressureElement { - unsigned PSetID; - int UnitIncrease; +/// Capture a change in pressure for a single pressure set. UnitInc may be +/// expressed in terms of upward or downward pressure depending on the client +/// and will be dynamically adjusted for current liveness. +/// +/// Pressure increments are tiny, typically 1-2 units, and this is only for +/// heuristics, so we don't check UnitInc overflow. Instead, we may have a +/// higher level assert that pressure is consistent within a region. We also +/// effectively ignore dead defs which don't affect heuristics much. +class PressureChange { + uint16_t PSetID; // ID+1. 0=Invalid. + int16_t UnitInc; +public: + PressureChange(): PSetID(0), UnitInc(0) {} + PressureChange(unsigned id): PSetID(id+1), UnitInc(0) { + assert(id < UINT16_MAX && "PSetID overflow."); + } + + bool isValid() const { return PSetID > 0; } + + unsigned getPSet() const { + assert(isValid() && "invalid PressureChange"); + return PSetID - 1; + } + // If PSetID is invalid, return UINT16_MAX to give it lowest priority. + unsigned getPSetOrMax() const { return (PSetID - 1) & UINT16_MAX; } + + int getUnitInc() const { return UnitInc; } - PressureElement(): PSetID(~0U), UnitIncrease(0) {} - PressureElement(unsigned id, int inc): PSetID(id), UnitIncrease(inc) {} + void setUnitInc(int Inc) { UnitInc = Inc; } - bool isValid() const { return PSetID != ~0U; } + bool operator==(const PressureChange &RHS) const { + return PSetID == RHS.PSetID && UnitInc == RHS.UnitInc; + } +}; - // If signed PSetID is negative, it is invalid; convert it to INT_MAX to give - // it lowest priority. - int PSetRank() const { return PSetID & INT_MAX; } +template <> struct isPodLike<PressureChange> { + static const bool value = true; +}; + +/// List of PressureChanges in order of increasing, unique PSetID. +/// +/// Use a small fixed number, because we can fit more PressureChanges in an +/// empty SmallVector than ever need to be tracked per register class. If more +/// PSets are affected, then we only track the most constrained. +class PressureDiff { + // The initial design was for MaxPSets=4, but that requires PSet partitions, + // which are not yet implemented. (PSet partitions are equivalent PSets given + // the register classes actually in use within the scheduling region.) + enum { MaxPSets = 16 }; + + PressureChange PressureChanges[MaxPSets]; +public: + typedef PressureChange* iterator; + typedef const PressureChange* const_iterator; + iterator begin() { return &PressureChanges[0]; } + iterator end() { return &PressureChanges[MaxPSets]; } + const_iterator begin() const { return &PressureChanges[0]; } + const_iterator end() const { return &PressureChanges[MaxPSets]; } + + void addPressureChange(unsigned RegUnit, bool IsDec, + const MachineRegisterInfo *MRI); +}; + +/// Array of PressureDiffs. +class PressureDiffs { + PressureDiff *PDiffArray; + unsigned Size; + unsigned Max; +public: + PressureDiffs(): PDiffArray(0), Size(0), Max(0) {} + ~PressureDiffs() { free(PDiffArray); } + + void clear() { Size = 0; } + + void init(unsigned N); + + PressureDiff &operator[](unsigned Idx) { + assert(Idx < Size && "PressureDiff index out of bounds"); + return PDiffArray[Idx]; + } + const PressureDiff &operator[](unsigned Idx) const { + return const_cast<PressureDiffs*>(this)->operator[](Idx); + } }; /// Store the effects of a change in pressure on things that MI scheduler cares @@ -120,11 +189,19 @@ struct PressureElement { /// CurrentMax records the largest increase in the tracker's max pressure that /// exceeds the current limit for some pressure set determined by the client. struct RegPressureDelta { - PressureElement Excess; - PressureElement CriticalMax; - PressureElement CurrentMax; + PressureChange Excess; + PressureChange CriticalMax; + PressureChange CurrentMax; RegPressureDelta() {} + + bool operator==(const RegPressureDelta &RHS) const { + return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax + && CurrentMax == RHS.CurrentMax; + } + bool operator!=(const RegPressureDelta &RHS) const { + return !operator==(RHS); + } }; /// \brief A set of live virtual registers and physical register units. @@ -135,7 +212,7 @@ struct LiveRegSet { SparseSet<unsigned> PhysRegs; SparseSet<unsigned, VirtReg2IndexFunctor> VirtRegs; - bool contains(unsigned Reg) { + bool contains(unsigned Reg) const { if (TargetRegisterInfo::isVirtualRegister(Reg)) return VirtRegs.count(Reg); return PhysRegs.count(Reg); @@ -215,6 +292,8 @@ public: MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false), TrackUntiedDefs(false) {} + void reset(); + void init(const MachineFunction *mf, const RegisterClassInfo *rci, const LiveIntervals *lis, const MachineBasicBlock *mbb, MachineBasicBlock::const_iterator pos, @@ -239,7 +318,7 @@ public: SlotIndex getCurrSlot() const; /// Recede across the previous instruction. - bool recede(); + bool recede(SmallVectorImpl<unsigned> *LiveUses = 0, PressureDiff *PDiff = 0); /// Advance across the current instruction. bool advance(); @@ -282,31 +361,39 @@ public: /// limit based on the tracker's current pressure, and record the number of /// excess register units of that pressure set introduced by this instruction. void getMaxUpwardPressureDelta(const MachineInstr *MI, + PressureDiff *PDiff, RegPressureDelta &Delta, - ArrayRef<PressureElement> CriticalPSets, + ArrayRef<PressureChange> CriticalPSets, ArrayRef<unsigned> MaxPressureLimit); + void getUpwardPressureDelta(const MachineInstr *MI, + /*const*/ PressureDiff &PDiff, + RegPressureDelta &Delta, + ArrayRef<PressureChange> CriticalPSets, + ArrayRef<unsigned> MaxPressureLimit) const; + /// Consider the pressure increase caused by traversing this instruction /// top-down. Find the pressure set with the most change beyond its pressure /// limit based on the tracker's current pressure, and record the number of /// excess register units of that pressure set introduced by this instruction. void getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, - ArrayRef<PressureElement> CriticalPSets, + ArrayRef<PressureChange> CriticalPSets, ArrayRef<unsigned> MaxPressureLimit); /// Find the pressure set with the most change beyond its pressure limit after /// traversing this instruction either upward or downward depending on the /// closed end of the current region. - void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, - ArrayRef<PressureElement> CriticalPSets, + void getMaxPressureDelta(const MachineInstr *MI, + RegPressureDelta &Delta, + ArrayRef<PressureChange> CriticalPSets, ArrayRef<unsigned> MaxPressureLimit) { if (isTopClosed()) return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, MaxPressureLimit); assert(isBottomClosed() && "Uninitialized pressure tracker"); - return getMaxUpwardPressureDelta(MI, Delta, CriticalPSets, + return getMaxUpwardPressureDelta(MI, 0, Delta, CriticalPSets, MaxPressureLimit); } @@ -337,7 +424,7 @@ public: void dump() const; protected: - const LiveInterval *getInterval(unsigned Reg) const; + const LiveRange *getLiveRange(unsigned Reg) const; void increaseRegPressure(ArrayRef<unsigned> Regs); void decreaseRegPressure(ArrayRef<unsigned> Regs); diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 41289a4..009b8a0 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -1,4 +1,4 @@ -//===-- CodeGen/RuntimeLibcall.h - Runtime Library Calls --------*- C++ -*-===// +//===-- CodeGen/RuntimeLibcalls.h - Runtime Library Calls -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -188,6 +188,11 @@ namespace RTLIB { NEARBYINT_F80, NEARBYINT_F128, NEARBYINT_PPCF128, + ROUND_F32, + ROUND_F64, + ROUND_F80, + ROUND_F128, + ROUND_PPCF128, FLOOR_F32, FLOOR_F64, FLOOR_F80, @@ -320,34 +325,65 @@ namespace RTLIB { SYNC_VAL_COMPARE_AND_SWAP_2, SYNC_VAL_COMPARE_AND_SWAP_4, SYNC_VAL_COMPARE_AND_SWAP_8, + SYNC_VAL_COMPARE_AND_SWAP_16, SYNC_LOCK_TEST_AND_SET_1, SYNC_LOCK_TEST_AND_SET_2, SYNC_LOCK_TEST_AND_SET_4, SYNC_LOCK_TEST_AND_SET_8, + SYNC_LOCK_TEST_AND_SET_16, SYNC_FETCH_AND_ADD_1, SYNC_FETCH_AND_ADD_2, SYNC_FETCH_AND_ADD_4, SYNC_FETCH_AND_ADD_8, + SYNC_FETCH_AND_ADD_16, SYNC_FETCH_AND_SUB_1, SYNC_FETCH_AND_SUB_2, SYNC_FETCH_AND_SUB_4, SYNC_FETCH_AND_SUB_8, + SYNC_FETCH_AND_SUB_16, SYNC_FETCH_AND_AND_1, SYNC_FETCH_AND_AND_2, SYNC_FETCH_AND_AND_4, SYNC_FETCH_AND_AND_8, + SYNC_FETCH_AND_AND_16, SYNC_FETCH_AND_OR_1, SYNC_FETCH_AND_OR_2, SYNC_FETCH_AND_OR_4, SYNC_FETCH_AND_OR_8, + SYNC_FETCH_AND_OR_16, SYNC_FETCH_AND_XOR_1, SYNC_FETCH_AND_XOR_2, SYNC_FETCH_AND_XOR_4, SYNC_FETCH_AND_XOR_8, + SYNC_FETCH_AND_XOR_16, SYNC_FETCH_AND_NAND_1, SYNC_FETCH_AND_NAND_2, SYNC_FETCH_AND_NAND_4, SYNC_FETCH_AND_NAND_8, + SYNC_FETCH_AND_NAND_16, + SYNC_FETCH_AND_MAX_1, + SYNC_FETCH_AND_MAX_2, + SYNC_FETCH_AND_MAX_4, + SYNC_FETCH_AND_MAX_8, + SYNC_FETCH_AND_MAX_16, + SYNC_FETCH_AND_UMAX_1, + SYNC_FETCH_AND_UMAX_2, + SYNC_FETCH_AND_UMAX_4, + SYNC_FETCH_AND_UMAX_8, + SYNC_FETCH_AND_UMAX_16, + SYNC_FETCH_AND_MIN_1, + SYNC_FETCH_AND_MIN_2, + SYNC_FETCH_AND_MIN_4, + SYNC_FETCH_AND_MIN_8, + SYNC_FETCH_AND_MIN_16, + SYNC_FETCH_AND_UMIN_1, + SYNC_FETCH_AND_UMIN_2, + SYNC_FETCH_AND_UMIN_4, + SYNC_FETCH_AND_UMIN_8, + SYNC_FETCH_AND_UMIN_16, + + // Stack Protector Fail. + STACKPROTECTOR_CHECK_FAIL, UNKNOWN_LIBCALL }; diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 371ac6c..ccba1b0 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -248,7 +248,7 @@ namespace llvm { /// SUnit - Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: - enum { BoundaryID = ~0u }; + enum LLVM_ENUM_INT_TYPE(unsigned) { BoundaryID = ~0u }; SDNode *Node; // Representative node. MachineInstr *Instr; // Alternatively, a MachineInstr. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 9ab1013..fe4f3c2 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -28,6 +28,7 @@ namespace llvm { class MachineDominatorTree; class LiveIntervals; class RegPressureTracker; + class PressureDiffs; /// An individual mapping from virtual register number to SUnit. struct VReg2SUnit { @@ -56,7 +57,8 @@ namespace llvm { /// Use a SparseMultiSet to track physical registers. Storage is only /// allocated once for the pass. It can be cleared in constant time and reused /// without any frees. - typedef SparseMultiSet<PhysRegSUOper, llvm::identity<unsigned>, uint16_t> Reg2SUnitsMap; + typedef SparseMultiSet<PhysRegSUOper, llvm::identity<unsigned>, uint16_t> + Reg2SUnitsMap; /// Use SparseSet as a SparseMap by relying on the fact that it never /// compares ValueT's, only unsigned keys. This allows the set to be cleared @@ -64,6 +66,11 @@ namespace llvm { /// require a destructor. typedef SparseSet<VReg2SUnit, VirtReg2IndexFunctor> VReg2SUnitMap; + /// Track local uses of virtual registers. These uses are gathered by the DAG + /// builder and may be consulted by the scheduler to avoid iterating an entire + /// vreg use list. + typedef SparseMultiSet<VReg2SUnit, VirtReg2IndexFunctor> VReg2UseMap; + /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of /// MachineInstrs. class ScheduleDAGInstrs : public ScheduleDAG { @@ -81,10 +88,6 @@ namespace llvm { /// isPostRA flag indicates vregs cannot be present. bool IsPostRA; - /// UnitLatencies (misnamed) flag avoids computing def-use latencies, using - /// the def-side latency only. - bool UnitLatencies; - /// The standard DAG builder does not normally include terminators as DAG /// nodes because it does not create the necessary dependencies to prevent /// reordering. A specialized scheduler can overide @@ -104,17 +107,18 @@ namespace llvm { /// The end of the range to be scheduled. MachineBasicBlock::iterator RegionEnd; - /// The index in BB of RegionEnd. - /// - /// This is the instruction number from the top of the current block, not - /// the SlotIndex. It is only used by the AntiDepBreaker and should be - /// removed once that client is obsolete. - unsigned EndIndex; + /// Instructions in this region (distance(RegionBegin, RegionEnd)). + unsigned NumRegionInstrs; /// After calling BuildSchedGraph, each machine instruction in the current /// scheduling region is mapped to an SUnit. DenseMap<MachineInstr*, SUnit*> MISUnitMap; + /// After calling BuildSchedGraph, each vreg used in the scheduling region + /// is mapped to a set of SUnits. These include all local vreg uses, not + /// just the uses for a singly defined vreg. + VReg2UseMap VRegUses; + /// State internal to DAG building. /// ------------------------------- @@ -125,7 +129,7 @@ namespace llvm { Reg2SUnitsMap Defs; Reg2SUnitsMap Uses; - /// Track the last instructon in this region defining each virtual register. + /// Track the last instruction in this region defining each virtual register. VReg2SUnitMap VRegDefs; /// PendingLoads - Remember where unknown loads are after the most recent @@ -185,14 +189,15 @@ namespace llvm { virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, - unsigned endcount); + unsigned regioninstrs); /// Notify that the scheduler has finished scheduling the current region. virtual void exitRegion(); /// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are /// input. - void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0); + void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0, + PressureDiffs *PDiffs = 0); /// addSchedBarrierDeps - Add dependencies from instructions in the current /// list of instructions being scheduled to scheduling barrier. We want to diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 79e533e..82becca 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -38,6 +38,45 @@ class TargetLowering; class TargetSelectionDAGInfo; class TargetTransformInfo; +class SDVTListNode : public FoldingSetNode { + friend struct FoldingSetTrait<SDVTListNode>; + /// FastID - A reference to an Interned FoldingSetNodeID for this node. + /// The Allocator in SelectionDAG holds the data. + /// SDVTList contains all types which are frequently accessed in SelectionDAG. + /// The size of this list is not expected big so it won't introduce memory penalty. + FoldingSetNodeIDRef FastID; + const EVT *VTs; + unsigned int NumVTs; + /// The hash value for SDVTList is fixed so cache it to avoid hash calculation + unsigned HashValue; +public: + SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) : + FastID(ID), VTs(VT), NumVTs(Num) { + HashValue = ID.ComputeHash(); + } + SDVTList getSDVTList() { + SDVTList result = {VTs, NumVTs}; + return result; + } +}; + +// Specialize FoldingSetTrait for SDVTListNode +// To avoid computing temp FoldingSetNodeID and hash value. +template<> struct FoldingSetTrait<SDVTListNode> : DefaultFoldingSetTrait<SDVTListNode> { + static void Profile(const SDVTListNode &X, FoldingSetNodeID& ID) { + ID = X.FastID; + } + static bool Equals(const SDVTListNode &X, const FoldingSetNodeID &ID, + unsigned IDHash, FoldingSetNodeID &TempID) { + if (X.HashValue != IDHash) + return false; + return ID == X.FastID; + } + static unsigned ComputeHash(const SDVTListNode &X, FoldingSetNodeID &TempID) { + return X.HashValue; + } +}; + template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> { private: mutable ilist_half_node<SDNode> Sentinel; @@ -131,6 +170,7 @@ class SelectionDAG { const TargetMachine &TM; const TargetSelectionDAGInfo &TSI; const TargetTransformInfo *TTI; + const TargetLowering *TLI; MachineFunction *MF; LLVMContext *Context; CodeGenOpt::Level OptLevel; @@ -197,6 +237,13 @@ public: virtual void NodeUpdated(SDNode *N); }; + /// NewNodesMustHaveLegalTypes - When true, additional steps are taken to + /// ensure that getConstant() and similar functions return DAG nodes that + /// have legal types. This is important after type legalization since + /// any illegally typed nodes generated after this point will not experience + /// type legalization. + bool NewNodesMustHaveLegalTypes; + private: /// DAGUpdateListener is a friend so it can manipulate the listener stack. friend struct DAGUpdateListener; @@ -222,7 +269,8 @@ public: /// init - Prepare this SelectionDAG to process code in the given /// MachineFunction. /// - void init(MachineFunction &mf, const TargetTransformInfo *TTI); + void init(MachineFunction &mf, const TargetTransformInfo *TTI, + const TargetLowering *TLI); /// clear - Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -231,9 +279,7 @@ public: MachineFunction &getMachineFunction() const { return *MF; } const TargetMachine &getTarget() const { return TM; } - const TargetLowering &getTargetLoweringInfo() const { - return *TM.getTargetLowering(); - } + const TargetLowering &getTargetLoweringInfo() const { return *TLI; } const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } const TargetTransformInfo *getTargetTransformInfo() const { return TTI; } LLVMContext *getContext() const {return Context; } @@ -677,6 +723,13 @@ public: AtomicOrdering Ordering, SynchronizationScope SynchScope); + /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// takes N operands. + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList, + SDValue* Ops, unsigned NumOps, MachineMemOperand *MMO, + AtomicOrdering Ordering, + SynchronizationScope SynchScope); + /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not @@ -708,11 +761,16 @@ public: MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, const MDNode *TBAAInfo = 0, const MDNode *Ranges = 0); + SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, + MachineMemOperand *MMO); SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, unsigned Alignment, const MDNode *TBAAInfo = 0); + SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, + SDValue Chain, SDValue Ptr, EVT MemVT, + MachineMemOperand *MMO); SDValue getIndexedLoad(SDValue OrigLoad, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, @@ -751,6 +809,10 @@ public: /// getMDNode - Return an MDNodeSDNode which holds an MDNode. SDValue getMDNode(const MDNode *MD); + /// getAddrSpaceCast - Return an AddrSpaceCastSDNode. + SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr, + unsigned SrcAS, unsigned DestAS); + /// getShiftAmountOperand - Return the specified value casted to /// the target's desired shift amount type. SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op); @@ -1068,6 +1130,30 @@ public: /// it cannot be inferred. unsigned InferPtrAlignment(SDValue Ptr) const; + /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type + /// which is split (or expanded) into two not necessarily identical pieces. + std::pair<EVT, EVT> GetSplitDestVTs(const EVT &VT) const; + + /// SplitVector - Split the vector with EXTRACT_SUBVECTOR using the provides + /// VTs and return the low/high part. + std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL, + const EVT &LoVT, const EVT &HiVT); + + /// SplitVector - Split the vector with EXTRACT_SUBVECTOR and return the + /// low/high part. + std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL) { + EVT LoVT, HiVT; + llvm::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType()); + return SplitVector(N, DL, LoVT, HiVT); + } + + /// SplitVectorOperand - Split the node's operand with EXTRACT_SUBVECTOR and + /// return the low/high part. + std::pair<SDValue, SDValue> SplitVectorOperand(const SDNode *N, unsigned OpNo) + { + return SplitVector(N->getOperand(OpNo), SDLoc(N)); + } + private: bool RemoveNodeFromCSEMaps(SDNode *N); void AddModifiedNodeToCSEMaps(SDNode *N); @@ -1086,7 +1172,7 @@ private: void allnodes_clear(); /// VTList - List of non-single value types. - std::vector<SDVTList> VTList; + FoldingSet<SDVTListNode> VTListMap; /// CondCodeNodes - Maps to auto-CSE operations. std::vector<CondCodeSDNode*> CondCodeNodes; diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 3d55d3a..b5ec8cb 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -113,6 +113,8 @@ public: OPC_MoveChild, OPC_MoveParent, OPC_CheckSame, + OPC_CheckChild0Same, OPC_CheckChild1Same, + OPC_CheckChild2Same, OPC_CheckChild3Same, OPC_CheckPatternPredicate, OPC_CheckPredicate, OPC_CheckOpcode, diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 987f290..70c15e6 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -372,7 +372,7 @@ public: /// \<target\>ISD namespace). bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } - /// isTargetMemoryOpcode - Test if this node has a target-specific + /// isTargetMemoryOpcode - Test if this node has a target-specific /// memory-referencing opcode (in the \<target\>ISD namespace and /// greater than FIRST_TARGET_MEMORY_OPCODE). bool isTargetMemoryOpcode() const { @@ -520,7 +520,9 @@ public: /// isPredecessorOf - Return true if this node is a predecessor of N. /// NOTE: Implemented on top of hasPredecessor and every bit as /// expensive. Use carefully. - bool isPredecessorOf(const SDNode *N) const { return N->hasPredecessor(this); } + bool isPredecessorOf(const SDNode *N) const { + return N->hasPredecessor(this); + } /// hasPredecessor - Return true if N is a predecessor of this node. /// N is either an operand of this node, or can be reached by recursively @@ -901,7 +903,8 @@ inline void SDUse::setNode(SDNode *N) { class UnarySDNode : public SDNode { SDUse Op; public: - UnarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, SDValue X) + UnarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X) : SDNode(Opc, Order, dl, VTs) { InitOperands(&Op, X); } @@ -912,7 +915,8 @@ public: class BinarySDNode : public SDNode { SDUse Ops[2]; public: - BinarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y) + BinarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X, SDValue Y) : SDNode(Opc, Order, dl, VTs) { InitOperands(Ops, X, Y); } @@ -938,13 +942,7 @@ public: class HandleSDNode : public SDNode { SDUse Op; public: - // FIXME: Remove the "noinline" attribute once <rdar://problem/5852746> is - // fixed. -#if __GNUC__==4 && __GNUC_MINOR__==2 && defined(__APPLE__) && !defined(__llvm__) - explicit __attribute__((__noinline__)) HandleSDNode(SDValue X) -#else explicit HandleSDNode(SDValue X) -#endif : SDNode(ISD::HANDLENODE, 0, DebugLoc(), getSDVTList(MVT::Other)) { InitOperands(&Op, X); } @@ -952,6 +950,23 @@ public: const SDValue &getValue() const { return Op; } }; +class AddrSpaceCastSDNode : public UnarySDNode { +private: + unsigned SrcAddrSpace; + unsigned DestAddrSpace; + +public: + AddrSpaceCastSDNode(unsigned Order, DebugLoc dl, EVT VT, SDValue X, + unsigned SrcAS, unsigned DestAS); + + unsigned getSrcAddressSpace() const { return SrcAddrSpace; } + unsigned getDestAddressSpace() const { return DestAddrSpace; } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ADDRSPACECAST; + } +}; + /// Abstact virtual class for operations for memory operations class MemSDNode : public SDNode { private: @@ -966,14 +981,15 @@ public: MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO); - MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, const SDValue *Ops, + MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO); bool readMem() const { return MMO->isLoad(); } bool writeMem() const { return MMO->isStore(); } /// Returns alignment and volatility of the memory access - unsigned getOriginalAlignment() const { + unsigned getOriginalAlignment() const { return MMO->getBaseAlignment(); } unsigned getAlignment() const { @@ -1090,7 +1106,8 @@ public: // Swp: swap value // SrcVal: address to update as a Value (used for MemOperand) // Align: alignment of memory - AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) @@ -1098,7 +1115,8 @@ public: InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Cmp, Swp); } - AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) @@ -1106,7 +1124,8 @@ public: InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Val); } - AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) @@ -1114,6 +1133,16 @@ public: InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr); } + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT, + SDValue* AllOps, SDUse *DynOps, unsigned NumOps, + MachineMemOperand *MMO, + AtomicOrdering Ordering, SynchronizationScope SynchScope) + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { + InitAtomic(Ordering, SynchScope); + assert((DynOps || NumOps <= array_lengthof(Ops)) && + "Too many ops for internal storage!"); + InitOperands(DynOps ? DynOps : Ops, AllOps, NumOps); + } const SDValue &getBasePtr() const { return getOperand(1); } const SDValue &getVal() const { return getOperand(2); } @@ -1286,8 +1315,9 @@ class GlobalAddressSDNode : public SDNode { int64_t Offset; unsigned char TargetFlags; friend class SelectionDAG; - GlobalAddressSDNode(unsigned Opc, unsigned Order, DebugLoc DL, const GlobalValue *GA, EVT VT, - int64_t o, unsigned char TargetFlags); + GlobalAddressSDNode(unsigned Opc, unsigned Order, DebugLoc DL, + const GlobalValue *GA, EVT VT, int64_t o, + unsigned char TargetFlags); public: const GlobalValue *getGlobal() const { return TheGlobal; } @@ -1351,21 +1381,22 @@ class ConstantPoolSDNode : public SDNode { friend class SelectionDAG; ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o, unsigned Align, unsigned char TF) - : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, DebugLoc(), - getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, + DebugLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), + TargetFlags(TF) { assert(Offset >= 0 && "Offset is too large"); Val.ConstVal = c; } ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, EVT VT, int o, unsigned Align, unsigned char TF) - : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, DebugLoc(), - getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, + DebugLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), + TargetFlags(TF) { assert(Offset >= 0 && "Offset is too large"); Val.MachineCPVal = v; Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1); } public: - bool isMachineConstantPoolEntry() const { return Offset < 0; @@ -1427,8 +1458,8 @@ class BasicBlockSDNode : public SDNode { /// blocks out of order when they're jumped to, which makes it a bit /// harder. Let's see if we need it first. explicit BasicBlockSDNode(MachineBasicBlock *mbb) - : SDNode(ISD::BasicBlock, 0, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) { - } + : SDNode(ISD::BasicBlock, 0, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) + {} public: MachineBasicBlock *getBasicBlock() const { return MBB; } @@ -1481,22 +1512,22 @@ public: return N->getOpcode() == ISD::SRCVALUE; } }; - + class MDNodeSDNode : public SDNode { const MDNode *MD; friend class SelectionDAG; explicit MDNodeSDNode(const MDNode *md) - : SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md) {} + : SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md) + {} public: - + const MDNode *getMD() const { return MD; } - + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MDNODE_SDNODE; } }; - class RegisterSDNode : public SDNode { unsigned Reg; friend class SelectionDAG; @@ -1568,7 +1599,7 @@ public: class ExternalSymbolSDNode : public SDNode { const char *Symbol; unsigned char TargetFlags; - + friend class SelectionDAG; ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT) : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, @@ -1600,14 +1631,15 @@ public: return N->getOpcode() == ISD::CONDCODE; } }; - + /// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the /// future and most targets don't support it. class CvtRndSatSDNode : public SDNode { ISD::CvtCode CvtCode; friend class SelectionDAG; - explicit CvtRndSatSDNode(EVT VT, unsigned Order, DebugLoc dl, const SDValue *Ops, - unsigned NumOps, ISD::CvtCode Code) + explicit CvtRndSatSDNode(EVT VT, unsigned Order, DebugLoc dl, + const SDValue *Ops, unsigned NumOps, + ISD::CvtCode Code) : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT), Ops, NumOps), CvtCode(Code) { assert(NumOps == 5 && "wrong number of operations"); @@ -1649,9 +1681,10 @@ class LSBaseSDNode : public MemSDNode { */ SDUse Ops[4]; public: - LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, SDValue *Operands, - unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM, - EVT MemVT, MachineMemOperand *MMO) + LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT, + MachineMemOperand *MMO) : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { SubclassData |= AM << 2; assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); @@ -1840,7 +1873,7 @@ template <> struct GraphTraits<SDNode*> { /// LargestSDNode - The largest SDNode class. /// -typedef LoadSDNode LargestSDNode; +typedef AtomicSDNode LargestSDNode; /// MostAlignedSDNode - The SDNode class with the greatest alignment /// requirement. diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h new file mode 100644 index 0000000..e90f22e --- /dev/null +++ b/include/llvm/CodeGen/StackMaps.h @@ -0,0 +1,175 @@ +//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_STACKMAPS +#define LLVM_STACKMAPS + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineInstr.h" +#include <map> +#include <vector> + +namespace llvm { + +class AsmPrinter; +class MCExpr; + +/// \brief MI-level patchpoint operands. +/// +/// MI patchpoint operations take the form: +/// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ... +/// +/// IR patchpoint intrinsics do not have the <cc> operand because calling +/// convention is part of the subclass data. +/// +/// SD patchpoint nodes do not have a def operand because it is part of the +/// SDValue. +/// +/// Patchpoints following the anyregcc convention are handled specially. For +/// these, the stack map also records the location of the return value and +/// arguments. +class PatchPointOpers { +public: + /// Enumerate the meta operands. + enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; +private: + const MachineInstr *MI; + bool HasDef; + bool IsAnyReg; +public: + explicit PatchPointOpers(const MachineInstr *MI); + + bool isAnyReg() const { return IsAnyReg; } + bool hasDef() const { return HasDef; } + + unsigned getMetaIdx(unsigned Pos = 0) const { + assert(Pos < MetaEnd && "Meta operand index out of range."); + return (HasDef ? 1 : 0) + Pos; + } + + const MachineOperand &getMetaOper(unsigned Pos) { + return MI->getOperand(getMetaIdx(Pos)); + } + + unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; } + + /// Get the operand index of the variable list of non-argument operands. + /// These hold the "live state". + unsigned getVarIdx() const { + return getMetaIdx() + MetaEnd + + MI->getOperand(getMetaIdx(NArgPos)).getImm(); + } + + /// Get the index at which stack map locations will be recorded. + /// Arguments are not recorded unless the anyregcc convention is used. + unsigned getStackMapStartIdx() const { + if (IsAnyReg) + return getArgIdx(); + return getVarIdx(); + } + + /// \brief Get the next scratch register operand index. + unsigned getNextScratchIdx(unsigned StartIdx = 0) const; +}; + +class StackMaps { +public: + struct Location { + enum LocationType { Unprocessed, Register, Direct, Indirect, Constant, + ConstantIndex }; + LocationType LocType; + unsigned Size; + unsigned Reg; + int64_t Offset; + Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {} + Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset) + : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {} + }; + + // Typedef a function pointer for functions that parse sequences of operands + // and return a Location, plus a new "next" operand iterator. + typedef std::pair<Location, MachineInstr::const_mop_iterator> + (*OperandParser)(MachineInstr::const_mop_iterator, + MachineInstr::const_mop_iterator, const TargetMachine&); + + // OpTypes are used to encode information about the following logical + // operand (which may consist of several MachineOperands) for the + // OpParser. + typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType; + + StackMaps(AsmPrinter &AP, OperandParser OpParser) + : AP(AP), OpParser(OpParser) {} + + /// \brief Generate a stackmap record for a stackmap instruction. + /// + /// MI must be a raw STACKMAP, not a PATCHPOINT. + void recordStackMap(const MachineInstr &MI); + + /// \brief Generate a stackmap record for a patchpoint instruction. + void recordPatchPoint(const MachineInstr &MI); + + /// If there is any stack map data, create a stack map section and serialize + /// the map info into it. This clears the stack map data structures + /// afterwards. + void serializeToStackMapSection(); + +private: + typedef SmallVector<Location, 8> LocationVec; + + struct CallsiteInfo { + const MCExpr *CSOffsetExpr; + unsigned ID; + LocationVec Locations; + CallsiteInfo() : CSOffsetExpr(0), ID(0) {} + CallsiteInfo(const MCExpr *CSOffsetExpr, unsigned ID, + LocationVec Locations) + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {} + }; + + typedef std::vector<CallsiteInfo> CallsiteInfoList; + + struct ConstantPool { + private: + typedef std::map<int64_t, size_t> ConstantsMap; + std::vector<int64_t> ConstantsList; + ConstantsMap ConstantIndexes; + + public: + size_t getNumConstants() const { return ConstantsList.size(); } + int64_t getConstant(size_t Idx) const { return ConstantsList[Idx]; } + size_t getConstantIndex(int64_t ConstVal) { + size_t NextIdx = ConstantsList.size(); + ConstantsMap::const_iterator I = + ConstantIndexes.insert(ConstantIndexes.end(), + std::make_pair(ConstVal, NextIdx)); + if (I->second == NextIdx) + ConstantsList.push_back(ConstVal); + return I->second; + } + }; + + AsmPrinter &AP; + OperandParser OpParser; + CallsiteInfoList CSInfos; + ConstantPool ConstPool; + + /// This should be called by the MC lowering code _immediately_ before + /// lowering the MI to an MCInst. It records where the operands for the + /// instruction are stored, and outputs a label to record the offset of + /// the call from the start of the text section. In special cases (e.g. AnyReg + /// calling convention) the return register is also recorded if requested. + void recordStackMapOpers(const MachineInstr &MI, uint32_t ID, + MachineInstr::const_mop_iterator MOI, + MachineInstr::const_mop_iterator MOE, + bool recordResult = false); +}; + +} + +#endif // LLVM_STACKMAPS diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h new file mode 100644 index 0000000..d09a933 --- /dev/null +++ b/include/llvm/CodeGen/StackProtector.h @@ -0,0 +1,127 @@ +//===-- StackProtector.h - Stack Protector Insertion ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass inserts stack protectors into functions which need them. A variable +// with a random value in it is stored onto the stack before the local variables +// are allocated. Upon exiting the block, the stored value is checked. If it's +// changed, then there was some sort of violation and the program aborts. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_STACKPROTECTOR_H +#define LLVM_CODEGEN_STACKPROTECTOR_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/ValueMap.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { +class DominatorTree; +class Function; +class Module; +class PHINode; + +class StackProtector : public FunctionPass { +public: + /// SSPLayoutKind. Stack Smashing Protection (SSP) rules require that + /// vulnerable stack allocations are located close the stack protector. + enum SSPLayoutKind { + SSPLK_None, ///< Did not trigger a stack protector. No effect on data + ///< layout. + SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest + ///< to the stack protector. + SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest + ///< to the stack protector. + SSPLK_AddrOf ///< The address of this allocation is exposed and + ///< triggered protection. 3rd closest to the protector. + }; + + /// A mapping of AllocaInsts to their required SSP layout. + typedef ValueMap<const AllocaInst *, SSPLayoutKind> SSPLayoutMap; + +private: + const TargetMachine *TM; + + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// target type sizes. + const TargetLoweringBase *TLI; + const Triple Trip; + + Function *F; + Module *M; + + DominatorTree *DT; + + /// Layout - Mapping of allocations to the required SSPLayoutKind. + /// StackProtector analysis will update this map when determining if an + /// AllocaInst triggers a stack protector. + SSPLayoutMap Layout; + + /// \brief The minimum size of buffers that will receive stack smashing + /// protection when -fstack-protection is used. + unsigned SSPBufferSize; + + /// VisitedPHIs - The set of PHI nodes visited when determining + /// if a variable's reference has been taken. This set + /// is maintained to ensure we don't visit the same PHI node multiple + /// times. + SmallPtrSet<const PHINode *, 16> VisitedPHIs; + + /// InsertStackProtectors - Insert code into the prologue and epilogue of + /// the function. + /// + /// - The prologue code loads and stores the stack guard onto the stack. + /// - The epilogue checks the value stored in the prologue against the + /// original value. It calls __stack_chk_fail if they differ. + bool InsertStackProtectors(); + + /// CreateFailBB - Create a basic block to jump to when the stack protector + /// check fails. + BasicBlock *CreateFailBB(); + + /// ContainsProtectableArray - Check whether the type either is an array or + /// contains an array of sufficient size so that we need stack protectors + /// for it. + /// \param [out] IsLarge is set to true if a protectable array is found and + /// it is "large" ( >= ssp-buffer-size). In the case of a structure with + /// multiple arrays, this gets set if any of them is large. + bool ContainsProtectableArray(Type *Ty, bool &IsLarge, bool Strong = false, + bool InStruct = false) const; + + /// \brief Check whether a stack allocation has its address taken. + bool HasAddressTaken(const Instruction *AI); + + /// RequiresStackProtector - Check whether or not this function needs a + /// stack protector based upon the stack protector level. + bool RequiresStackProtector(); + +public: + static char ID; // Pass identification, replacement for typeid. + StackProtector() : FunctionPass(ID), TM(0), TLI(0), SSPBufferSize(0) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + StackProtector(const TargetMachine *TM) + : FunctionPass(ID), TM(TM), TLI(0), Trip(TM->getTargetTriple()), + SSPBufferSize(8) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved<DominatorTree>(); + } + + SSPLayoutKind getSSPLayout(const AllocaInst *AI) const; + + virtual bool runOnFunction(Function &Fn); +}; +} // end namespace llvm + +#endif // LLVM_CODEGEN_STACKPROTECTOR_H diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index f2adcf8..8ef26b7 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -152,7 +152,13 @@ public: /// Compute and return the expected latency of this instruction independent of /// a particular use. computeOperandLatency is the prefered API, but this is /// occasionally useful to help estimate instruction cost. - unsigned computeInstrLatency(const MachineInstr *MI) const; + /// + /// If UseDefaultDefLatency is false and no new machine sched model is + /// present this method falls back to TII->getInstrLatency with an empty + /// instruction itinerary (this is so we preserve the previous behavior of the + /// if converter after moving it to TargetSchedModel). + unsigned computeInstrLatency(const MachineInstr *MI, + bool UseDefaultDefLatency = true) const; /// \brief Output dependency latency of a pair of defs of the same register. /// diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index b7b3d73..79f3233 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -27,9 +27,9 @@ namespace llvm { class LLVMContext; struct EVT; - /// MVT - Machine Value Type. Every type that is supported natively by some - /// processor targeted by LLVM occurs here. This means that any legal value - /// type can be represented by a MVT. + /// MVT - Machine Value Type. Every type that is supported natively by some + /// processor targeted by LLVM occurs here. This means that any legal value + /// type can be represented by an MVT. class MVT { public: enum SimpleValueType { @@ -67,40 +67,45 @@ namespace llvm { v32i1 = 17, // 32 x i1 v64i1 = 18, // 64 x i1 - v2i8 = 19, // 2 x i8 - v4i8 = 20, // 4 x i8 - v8i8 = 21, // 8 x i8 - v16i8 = 22, // 16 x i8 - v32i8 = 23, // 32 x i8 - v64i8 = 24, // 64 x i8 - v1i16 = 25, // 1 x i16 - v2i16 = 26, // 2 x i16 - v4i16 = 27, // 4 x i16 - v8i16 = 28, // 8 x i16 - v16i16 = 29, // 16 x i16 - v32i16 = 30, // 32 x i16 - v1i32 = 31, // 1 x i32 - v2i32 = 32, // 2 x i32 - v4i32 = 33, // 4 x i32 - v8i32 = 34, // 8 x i32 - v16i32 = 35, // 16 x i32 - v1i64 = 36, // 1 x i64 - v2i64 = 37, // 2 x i64 - v4i64 = 38, // 4 x i64 - v8i64 = 39, // 8 x i64 - v16i64 = 40, // 16 x i64 + v1i8 = 19, // 1 x i8 + v2i8 = 20, // 2 x i8 + v4i8 = 21, // 4 x i8 + v8i8 = 22, // 8 x i8 + v16i8 = 23, // 16 x i8 + v32i8 = 24, // 32 x i8 + v64i8 = 25, // 64 x i8 + v1i16 = 26, // 1 x i16 + v2i16 = 27, // 2 x i16 + v4i16 = 28, // 4 x i16 + v8i16 = 29, // 8 x i16 + v16i16 = 30, // 16 x i16 + v32i16 = 31, // 32 x i16 + v1i32 = 32, // 1 x i32 + v2i32 = 33, // 2 x i32 + v4i32 = 34, // 4 x i32 + v8i32 = 35, // 8 x i32 + v16i32 = 36, // 16 x i32 + v1i64 = 37, // 1 x i64 + v2i64 = 38, // 2 x i64 + v4i64 = 39, // 4 x i64 + v8i64 = 40, // 8 x i64 + v16i64 = 41, // 16 x i64 FIRST_INTEGER_VECTOR_VALUETYPE = v2i1, LAST_INTEGER_VECTOR_VALUETYPE = v16i64, - v2f16 = 41, // 2 x f16 - v2f32 = 42, // 2 x f32 - v4f32 = 43, // 4 x f32 - v8f32 = 44, // 8 x f32 - v16f32 = 45, // 16 x f32 - v2f64 = 46, // 2 x f64 - v4f64 = 47, // 4 x f64 - v8f64 = 48, // 8 x f64 + v2f16 = 42, // 2 x f16 + v4f16 = 43, // 4 x f16 + v8f16 = 44, // 8 x f16 + v1f32 = 45, // 1 x f32 + v2f32 = 46, // 2 x f32 + v4f32 = 47, // 4 x f32 + v8f32 = 48, // 8 x f32 + v16f32 = 49, // 16 x f32 + v1f64 = 50, // 1 x f64 + v2f64 = 51, // 2 x f64 + v4f64 = 52, // 4 x f64 + v8f64 = 53, // 8 x f64 FIRST_FP_VECTOR_VALUETYPE = v2f16, LAST_FP_VECTOR_VALUETYPE = v8f64, @@ -108,17 +113,17 @@ namespace llvm { FIRST_VECTOR_VALUETYPE = v2i1, LAST_VECTOR_VALUETYPE = v8f64, - x86mmx = 49, // This is an X86 MMX value + x86mmx = 54, // This is an X86 MMX value - Glue = 50, // This glues nodes together during pre-RA sched + Glue = 55, // This glues nodes together during pre-RA sched - isVoid = 51, // This has no value + isVoid = 56, // This has no value - Untyped = 52, // This value takes a register, but has + Untyped = 57, // This value takes a register, but has // unspecified type. The register class // will be determined by the opcode. - LAST_VALUETYPE = 53, // This always remains at the end of the list. + LAST_VALUETYPE = 58, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors @@ -203,7 +208,7 @@ namespace llvm { bool is64BitVector() const { return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || - SimpleTy == MVT::v2f32); + SimpleTy == MVT::v1f64 || SimpleTy == MVT::v2f32); } /// is128BitVector - Return true if this is a 128-bit vector type. @@ -265,6 +270,7 @@ namespace llvm { case v16i1 : case v32i1 : case v64i1: return i1; + case v1i8 : case v2i8 : case v4i8 : case v8i8 : @@ -287,11 +293,15 @@ namespace llvm { case v4i64: case v8i64: case v16i64: return i64; - case v2f16: return f16; + case v2f16: + case v4f16: + case v8f16: return f16; + case v1f32: case v2f32: case v4f32: case v8f32: case v16f32: return f32; + case v1f64: case v2f64: case v4f64: case v8f64: return f64; @@ -318,6 +328,7 @@ namespace llvm { case v8i16: case v8i32: case v8i64: + case v8f16: case v8f32: case v8f64: return 8; case v4i1: @@ -325,6 +336,7 @@ namespace llvm { case v4i16: case v4i32: case v4i64: + case v4f16: case v4f32: case v4f64: return 4; case v2i1: @@ -335,9 +347,12 @@ namespace llvm { case v2f16: case v2f32: case v2f64: return 2; + case v1i8: case v1i16: case v1i32: - case v1i64: return 1; + case v1i64: + case v1f32: + case v1f64: return 1; } } @@ -360,6 +375,7 @@ namespace llvm { case v2i1: return 2; case v4i1: return 4; case i8 : + case v1i8: case v8i1: return 8; case i16 : case f16: @@ -372,6 +388,7 @@ namespace llvm { case v4i8: case v2i16: case v2f16: + case v1f32: case v1i32: return 32; case x86mmx: case f64 : @@ -381,7 +398,9 @@ namespace llvm { case v4i16: case v2i32: case v1i64: - case v2f32: return 64; + case v4f16: + case v2f32: + case v1f64: return 64; case f80 : return 80; case f128: case ppcf128: @@ -390,6 +409,7 @@ namespace llvm { case v8i16: case v4i32: case v2i64: + case v8f16: case v4f32: case v2f64: return 128; case v32i8: @@ -490,6 +510,7 @@ namespace llvm { if (NumElements == 64) return MVT::v64i1; break; case MVT::i8: + if (NumElements == 1) return MVT::v1i8; if (NumElements == 2) return MVT::v2i8; if (NumElements == 4) return MVT::v4i8; if (NumElements == 8) return MVT::v8i8; @@ -521,14 +542,18 @@ namespace llvm { break; case MVT::f16: if (NumElements == 2) return MVT::v2f16; + if (NumElements == 4) return MVT::v4f16; + if (NumElements == 8) return MVT::v8f16; break; case MVT::f32: + if (NumElements == 1) return MVT::v1f32; if (NumElements == 2) return MVT::v2f32; if (NumElements == 4) return MVT::v4f32; if (NumElements == 8) return MVT::v8f32; if (NumElements == 16) return MVT::v16f32; break; case MVT::f64: + if (NumElements == 1) return MVT::v1f64; if (NumElements == 2) return MVT::v2f64; if (NumElements == 4) return MVT::v4f64; if (NumElements == 8) return MVT::v8f64; diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index da26985..b5fa0e8 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -26,7 +26,7 @@ def i16 : ValueType<16 , 3>; // 16-bit integer value def i32 : ValueType<32 , 4>; // 32-bit integer value def i64 : ValueType<64 , 5>; // 64-bit integer value def i128 : ValueType<128, 6>; // 128-bit integer value -def f16 : ValueType<16 , 7>; // 32-bit floating point value +def f16 : ValueType<16 , 7>; // 16-bit floating point value def f32 : ValueType<32 , 8>; // 32-bit floating point value def f64 : ValueType<64 , 9>; // 64-bit floating point value def f80 : ValueType<80 , 10>; // 80-bit floating point value @@ -39,43 +39,48 @@ def v8i1 : ValueType<8 , 15>; // 8 x i1 vector value def v16i1 : ValueType<16, 16>; // 16 x i1 vector value def v32i1 : ValueType<32 , 17>; // 32 x i1 vector value def v64i1 : ValueType<64 , 18>; // 64 x i1 vector value -def v2i8 : ValueType<16 , 19>; // 2 x i8 vector value -def v4i8 : ValueType<32 , 20>; // 4 x i8 vector value -def v8i8 : ValueType<64 , 21>; // 8 x i8 vector value -def v16i8 : ValueType<128, 22>; // 16 x i8 vector value -def v32i8 : ValueType<256, 23>; // 32 x i8 vector value -def v64i8 : ValueType<512, 24>; // 64 x i8 vector value -def v1i16 : ValueType<16 , 25>; // 1 x i16 vector value -def v2i16 : ValueType<32 , 26>; // 2 x i16 vector value -def v4i16 : ValueType<64 , 27>; // 4 x i16 vector value -def v8i16 : ValueType<128, 28>; // 8 x i16 vector value -def v16i16 : ValueType<256, 29>; // 16 x i16 vector value -def v32i16 : ValueType<512, 30>; // 32 x i16 vector value -def v1i32 : ValueType<32 , 31>; // 1 x i32 vector value -def v2i32 : ValueType<64 , 32>; // 2 x i32 vector value -def v4i32 : ValueType<128, 33>; // 4 x i32 vector value -def v8i32 : ValueType<256, 34>; // 8 x i32 vector value -def v16i32 : ValueType<512, 35>; // 16 x i32 vector value -def v1i64 : ValueType<64 , 36>; // 1 x i64 vector value -def v2i64 : ValueType<128, 37>; // 2 x i64 vector value -def v4i64 : ValueType<256, 38>; // 4 x i64 vector value -def v8i64 : ValueType<512, 39>; // 8 x i64 vector value -def v16i64 : ValueType<1024,40>; // 16 x i64 vector value +def v1i8 : ValueType<16, 19>; // 1 x i8 vector value +def v2i8 : ValueType<16 , 20>; // 2 x i8 vector value +def v4i8 : ValueType<32 , 21>; // 4 x i8 vector value +def v8i8 : ValueType<64 , 22>; // 8 x i8 vector value +def v16i8 : ValueType<128, 23>; // 16 x i8 vector value +def v32i8 : ValueType<256, 24>; // 32 x i8 vector value +def v64i8 : ValueType<512, 25>; // 64 x i8 vector value +def v1i16 : ValueType<16 , 26>; // 1 x i16 vector value +def v2i16 : ValueType<32 , 27>; // 2 x i16 vector value +def v4i16 : ValueType<64 , 28>; // 4 x i16 vector value +def v8i16 : ValueType<128, 29>; // 8 x i16 vector value +def v16i16 : ValueType<256, 30>; // 16 x i16 vector value +def v32i16 : ValueType<512, 31>; // 32 x i16 vector value +def v1i32 : ValueType<32 , 32>; // 1 x i32 vector value +def v2i32 : ValueType<64 , 33>; // 2 x i32 vector value +def v4i32 : ValueType<128, 34>; // 4 x i32 vector value +def v8i32 : ValueType<256, 35>; // 8 x i32 vector value +def v16i32 : ValueType<512, 36>; // 16 x i32 vector value +def v1i64 : ValueType<64 , 37>; // 1 x i64 vector value +def v2i64 : ValueType<128, 38>; // 2 x i64 vector value +def v4i64 : ValueType<256, 39>; // 4 x i64 vector value +def v8i64 : ValueType<512, 40>; // 8 x i64 vector value +def v16i64 : ValueType<1024,41>; // 16 x i64 vector value -def v2f16 : ValueType<32 , 41>; // 2 x f16 vector value -def v2f32 : ValueType<64 , 42>; // 2 x f32 vector value -def v4f32 : ValueType<128, 43>; // 4 x f32 vector value -def v8f32 : ValueType<256, 44>; // 8 x f32 vector value -def v16f32 : ValueType<512, 45>; // 16 x f32 vector value -def v2f64 : ValueType<128, 46>; // 2 x f64 vector value -def v4f64 : ValueType<256, 47>; // 4 x f64 vector value -def v8f64 : ValueType<512, 48>; // 8 x f64 vector value +def v2f16 : ValueType<32 , 42>; // 2 x f16 vector value +def v4f16 : ValueType<64 , 43>; // 4 x f16 vector value +def v8f16 : ValueType<128, 44>; // 8 x f16 vector value +def v1f32 : ValueType<32 , 45>; // 1 x f32 vector value +def v2f32 : ValueType<64 , 46>; // 2 x f32 vector value +def v4f32 : ValueType<128, 47>; // 4 x f32 vector value +def v8f32 : ValueType<256, 48>; // 8 x f32 vector value +def v16f32 : ValueType<512, 49>; // 16 x f32 vector value +def v1f64 : ValueType<64, 50>; // 1 x f64 vector value +def v2f64 : ValueType<128, 51>; // 2 x f64 vector value +def v4f64 : ValueType<256, 52>; // 4 x f64 vector value +def v8f64 : ValueType<512, 53>; // 8 x f64 vector value -def x86mmx : ValueType<64 , 49>; // X86 MMX value -def FlagVT : ValueType<0 , 50>; // Pre-RA sched glue -def isVoid : ValueType<0 , 51>; // Produces no value -def untyped: ValueType<8 , 52>; // Produces an untyped value +def x86mmx : ValueType<64 , 54>; // X86 MMX value +def FlagVT : ValueType<0 , 55>; // Pre-RA sched glue +def isVoid : ValueType<0 , 56>; // Produces no value +def untyped: ValueType<8 , 57>; // Produces an untyped value def MetadataVT: ValueType<0, 250>; // Metadata // Pseudo valuetype mapped to the current pointer size to any address space. diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 4b0aa4b..5c72ad8 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -21,6 +21,9 @@ /* Define if you want backtraces on crash */ #cmakedefine ENABLE_BACKTRACES +/* Define to enable crash overrides */ +#cmakedefine ENABLE_CRASH_OVERRIDES + /* Define if position independent code is enabled */ #cmakedefine ENABLE_PIC @@ -48,12 +51,6 @@ /* Define to 1 if you have the `closedir' function. */ #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} -/* Define if curses provides the has_color() function on this platform. */ -#cmakedefine HAVE_CURSES - -/* Define to 1 if you have the <curses.h> header file. */ -#cmakedefine HAVE_CURSES_H - /* Define to 1 if you have the <cxxabi.h> header file. */ #cmakedefine HAVE_CXXABI_H ${HAVE_CXXABI_H} @@ -132,13 +129,13 @@ #cmakedefine HAVE_LOG10 ${HAVE_LOG10} /* Define to 1 if you have the `exp' function. */ -#cmakedefine HAVE_EXP ${HAVE_LOG} +#cmakedefine HAVE_EXP ${HAVE_EXP} /* Define to 1 if you have the `exp2' function. */ -#cmakedefine HAVE_EXP2 ${HAVE_LOG2} +#cmakedefine HAVE_EXP2 ${HAVE_EXP2} /* Define to 1 if you have the `exp10' function. */ -#cmakedefine HAVE_EXP10 ${HAVE_LOG10} +#cmakedefine HAVE_EXP10 ${HAVE_EXP10} /* Define to 1 if you have the `fmodf' function. */ #cmakedefine HAVE_FMODF ${HAVE_FMODF} @@ -206,6 +203,9 @@ /* Define to 1 if you have the `pthread' library (-lpthread). */ #cmakedefine HAVE_LIBPTHREAD ${HAVE_LIBPTHREAD} +/* Define to 1 if you have the `shell32' library (-lshell32). */ +#cmakedefine HAVE_LIBSHELL32 ${HAVE_LIBSHELL32} + /* Define to 1 if you have the `udis86' library (-ludis86). */ #undef HAVE_LIBUDIS86 @@ -262,18 +262,6 @@ /* Define if mmap() can map files into memory */ #undef HAVE_MMAP_FILE -/* Define to 1 if you have the <ncursesw/curses.h> header file. */ -#cmakedefine HAVE_NCURSESW_CURSES_H - -/* Define to 1 if you have the <ncursesw.h> header file. */ -#cmakedefine HAVE_NCURSESW_H - -/* Define to 1 if you have the <ncurses/curses.h> header file. */ -#cmakedefine HAVE_NCURSES_CURSES_H - -/* Define to 1 if you have the <ncurses.h> header file. */ -#cmakedefine HAVE_NCURSES_H - /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #cmakedefine HAVE_NDIR_H ${HAVE_NDIR_H} @@ -320,7 +308,7 @@ #cmakedefine HAVE_READDIR ${HAVE_READDIR} /* Define to 1 if you have the `realpath' function. */ -#undef HAVE_REALPATH +#cmakedefine HAVE_REALPATH ${HAVE_REALPATH} /* Define to 1 if you have the `rintf' function. */ #undef HAVE_RINTF @@ -420,6 +408,9 @@ /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ #cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H} +/* Define if the setupterm() function is supported this platform. */ +#cmakedefine HAVE_TERMINFO ${HAVE_TERMINFO} + /* Define to 1 if you have the <termios.h> header file. */ #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 7bb1caa..dcec8f8 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -3,6 +3,9 @@ #ifndef CONFIG_H #define CONFIG_H +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + /* Bug report URL. */ #undef BUG_REPORT_URL @@ -21,6 +24,9 @@ /* Define if you want backtraces on crash */ #undef ENABLE_BACKTRACES +/* Define to enable crash handling overrides */ +#undef ENABLE_CRASH_OVERRIDES + /* Define if position independent code is enabled */ #undef ENABLE_PIC @@ -69,12 +75,6 @@ /* can use __crashreporter_info__ */ #undef HAVE_CRASHREPORTER_INFO -/* Define if curses provides the has_color() function on this platform. */ -#undef HAVE_CURSES - -/* Define to 1 if you have the <curses.h> header file. */ -#undef HAVE_CURSES_H - /* Define to 1 if you have the <cxxabi.h> header file. */ #undef HAVE_CXXABI_H @@ -220,6 +220,9 @@ /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD +/* Define to 1 if you have the `shell32' library (-lshell32). */ +#undef HAVE_LIBSHELL32 + /* Define to 1 if you have the `udis86' library (-ludis86). */ #undef HAVE_LIBUDIS86 @@ -288,18 +291,6 @@ /* Define if mmap() can map files into memory */ #undef HAVE_MMAP_FILE -/* Define to 1 if you have the <ncursesw/curses.h> header file. */ -#undef HAVE_NCURSESW_CURSES_H - -/* Define to 1 if you have the <ncursesw.h> header file. */ -#undef HAVE_NCURSESW_H - -/* Define to 1 if you have the <ncurses/curses.h> header file. */ -#undef HAVE_NCURSES_CURSES_H - -/* Define to 1 if you have the <ncurses.h> header file. */ -#undef HAVE_NCURSES_H - /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #undef HAVE_NDIR_H @@ -455,6 +446,9 @@ /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H +/* Define if the setupterm() function is supported this platform. */ +#undef HAVE_TERMINFO + /* Define to 1 if you have the <termios.h> header file. */ #undef HAVE_TERMIOS_H @@ -679,6 +673,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION @@ -703,6 +700,18 @@ /* Type of 1st arg on ELM Callback */ #undef WIN32_ELMCB_PCSTR +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + /* Define to empty if `const' does not conform to ANSI C. */ #undef const diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index a15d619..bac1679 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -17,7 +17,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ValueHandle.h" namespace llvm { class BasicBlock; @@ -65,7 +67,9 @@ namespace llvm { Function *ValueFn; // llvm.dbg.value SmallVector<Value *, 4> AllEnumTypes; - SmallVector<Value *, 4> AllRetainTypes; + /// Use TrackingVH to collect RetainTypes, since they can be updated + /// later on. + SmallVector<TrackingVH<MDNode>, 4> AllRetainTypes; SmallVector<Value *, 4> AllSubprograms; SmallVector<Value *, 4> AllGVs; SmallVector<Value *, 4> AllImportedModules; @@ -279,13 +283,15 @@ namespace llvm { /// DW_AT_containing_type. See DWARF documentation /// for more info. /// @param TemplateParms Template type parameters. + /// @param UniqueIdentifier A unique identifier for the class. DICompositeType createClassType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, - MDNode *VTableHolder = 0, - MDNode *TemplateParms = 0); + DIType VTableHolder = DIType(), + MDNode *TemplateParms = 0, + StringRef UniqueIdentifier = StringRef()); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. @@ -297,12 +303,14 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. + /// @param UniqueIdentifier A unique identifier for the struct. DICompositeType createStructType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, unsigned RunTimeLang = 0, - MDNode *VTableHolder = 0); + DIType VTableHolder = DIType(), + StringRef UniqueIdentifier = StringRef()); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. @@ -314,10 +322,12 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. + /// @param UniqueIdentifier A unique identifier for the union. DICompositeType createUnionType( DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0); + DIArray Elements, unsigned RunTimeLang = 0, + StringRef UniqueIdentifier = StringRef()); /// createTemplateTypeParameter - Create debugging information for template /// type parameter. @@ -398,12 +408,11 @@ namespace llvm { /// @param AlignInBits Member alignment. /// @param Elements Enumeration elements. /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. + /// @param UniqueIdentifier A unique identifier for the enum. DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - DIArray Elements, - DIType UnderlyingType); + DIFile File, unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, + StringRef UniqueIdentifier = StringRef()); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -419,9 +428,12 @@ namespace llvm { DIType createObjectPointerType(DIType Ty); /// createForwardDecl - Create a temporary forward-declared type. - DIType createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, - DIFile F, unsigned Line, unsigned RuntimeLang = 0, - uint64_t SizeInBits = 0, uint64_t AlignInBits = 0); + DICompositeType createForwardDecl(unsigned Tag, StringRef Name, + DIDescriptor Scope, DIFile F, + unsigned Line, unsigned RuntimeLang = 0, + uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, + StringRef UniqueIdentifier = StringRef()); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. @@ -495,7 +507,7 @@ namespace llvm { /// @param AlwaysPreserve Boolean. Set to true if debug info for this /// variable should be preserved in optimized build. /// @param Flags Flags, e.g. artificial variable. - /// @param ArgNo If this variable is an arugment then this argument's + /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, @@ -515,7 +527,7 @@ namespace llvm { /// @param LineNo Line number. /// @param Ty Variable Type /// @param Addr An array of complex address operations. - /// @param ArgNo If this variable is an arugment then this argument's + /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, @@ -550,6 +562,20 @@ namespace llvm { MDNode *TParam = 0, MDNode *Decl = 0); + /// FIXME: this is added for dragonegg. Once we update dragonegg + /// to call resolve function, this will be removed. + DISubprogram createFunction(DIScopeRef Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DICompositeType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned ScopeLine, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0, + MDNode *TParam = 0, + MDNode *Decl = 0); + /// createMethod - Create a new descriptor for the specified C++ method. /// See comments in DISubprogram for descriptions of these fields. /// @param Scope Function scope. @@ -575,7 +601,7 @@ namespace llvm { DICompositeType Ty, bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, unsigned VTableIndex = 0, - MDNode *VTableHolder = 0, + DIType VTableHolder = DIType(), unsigned Flags = 0, bool isOptimized = false, Function *Fn = 0, diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h index f7e6434..768cf4e 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -17,780 +17,834 @@ #ifndef LLVM_DEBUGINFO_H #define LLVM_DEBUGINFO_H +#include "llvm/Support/Casting.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/Dwarf.h" namespace llvm { - class BasicBlock; - class Constant; - class Function; - class GlobalVariable; - class Module; - class Type; - class Value; - class DbgDeclareInst; - class DbgValueInst; - class Instruction; - class MDNode; - class NamedMDNode; - class LLVMContext; - class raw_ostream; - - class DIFile; - class DISubprogram; - class DILexicalBlock; - class DILexicalBlockFile; - class DIVariable; - class DIType; - class DIObjCProperty; - - /// DIDescriptor - A thin wraper around MDNode to access encoded debug info. - /// This should not be stored in a container, because the underlying MDNode - /// may change in certain situations. - class DIDescriptor { - public: - enum { - FlagPrivate = 1 << 0, - FlagProtected = 1 << 1, - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, - FlagBlockByrefStruct = 1 << 4, - FlagVirtual = 1 << 5, - FlagArtificial = 1 << 6, - FlagExplicit = 1 << 7, - FlagPrototyped = 1 << 8, - FlagObjcClassComplete = 1 << 9, - FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11, - FlagStaticMember = 1 << 12, - FlagIndirectVariable = 1 << 13 - }; - protected: - const MDNode *DbgNode; - - StringRef getStringField(unsigned Elt) const; - unsigned getUnsignedField(unsigned Elt) const { - return (unsigned)getUInt64Field(Elt); - } - uint64_t getUInt64Field(unsigned Elt) const; - int64_t getInt64Field(unsigned Elt) const; - DIDescriptor getDescriptorField(unsigned Elt) const; - - template <typename DescTy> - DescTy getFieldAs(unsigned Elt) const { - return DescTy(getDescriptorField(Elt)); - } - - GlobalVariable *getGlobalVariableField(unsigned Elt) const; - Constant *getConstantField(unsigned Elt) const; - Function *getFunctionField(unsigned Elt) const; - void replaceFunctionField(unsigned Elt, Function *F); - - public: - explicit DIDescriptor(const MDNode *N = 0) : DbgNode(N) {} - - bool Verify() const; - - operator MDNode *() const { return const_cast<MDNode*>(DbgNode); } - MDNode *operator ->() const { return const_cast<MDNode*>(DbgNode); } - - // An explicit operator bool so that we can do testing of DI values - // easily. - // FIXME: This operator bool isn't actually protecting anything at the - // moment due to the conversion operator above making DIDescriptor nodes - // implicitly convertable to bool. - LLVM_EXPLICIT operator bool() const { return DbgNode != 0; } - - bool operator==(DIDescriptor Other) const { - return DbgNode == Other.DbgNode; - } - bool operator!=(DIDescriptor Other) const { - return !operator==(Other); - } - - unsigned getTag() const { - return getUnsignedField(0) & ~LLVMDebugVersionMask; - } - - bool isDerivedType() const; - bool isCompositeType() const; - bool isBasicType() const; - bool isVariable() const; - bool isSubprogram() const; - bool isGlobalVariable() const; - bool isScope() const; - bool isFile() const; - bool isCompileUnit() const; - bool isNameSpace() const; - bool isLexicalBlockFile() const; - bool isLexicalBlock() const; - bool isSubrange() const; - bool isEnumerator() const; - bool isType() const; - bool isUnspecifiedParameter() const; - bool isTemplateTypeParameter() const; - bool isTemplateValueParameter() const; - bool isObjCProperty() const; - bool isImportedEntity() const; - - /// print - print descriptor. - void print(raw_ostream &OS) const; - - /// dump - print descriptor to dbgs() with a newline. - void dump() const; +class BasicBlock; +class Constant; +class Function; +class GlobalVariable; +class Module; +class Type; +class Value; +class DbgDeclareInst; +class DbgValueInst; +class Instruction; +class MDNode; +class MDString; +class NamedMDNode; +class LLVMContext; +class raw_ostream; + +class DIFile; +class DISubprogram; +class DILexicalBlock; +class DILexicalBlockFile; +class DIVariable; +class DIType; +class DIScope; +class DIObjCProperty; + +/// Maps from type identifier to the actual MDNode. +typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap; + +/// DIDescriptor - A thin wraper around MDNode to access encoded debug info. +/// This should not be stored in a container, because the underlying MDNode +/// may change in certain situations. +class DIDescriptor { + // Befriends DIRef so DIRef can befriend the protected member + // function: getFieldAs<DIRef>. + template <typename T> friend class DIRef; + +public: + enum { + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1, + FlagFwdDecl = 1 << 2, + FlagAppleBlock = 1 << 3, + FlagBlockByrefStruct = 1 << 4, + FlagVirtual = 1 << 5, + FlagArtificial = 1 << 6, + FlagExplicit = 1 << 7, + FlagPrototyped = 1 << 8, + FlagObjcClassComplete = 1 << 9, + FlagObjectPointer = 1 << 10, + FlagVector = 1 << 11, + FlagStaticMember = 1 << 12, + FlagIndirectVariable = 1 << 13 }; - /// DISubrange - This is used to represent ranges, for array bounds. - class DISubrange : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} - - int64_t getLo() const { return getInt64Field(1); } - int64_t getCount() const { return getInt64Field(2); } - bool Verify() const; - }; - - /// DIArray - This descriptor holds an array of descriptors. - class DIArray : public DIDescriptor { - public: - explicit DIArray(const MDNode *N = 0) : DIDescriptor(N) {} - - unsigned getNumElements() const; - DIDescriptor getElement(unsigned Idx) const { - return getDescriptorField(Idx); - } - }; - - /// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). - /// FIXME: it seems strange that this doesn't have either a reference to the - /// type/precision or a file/line pair for location info. - class DIEnumerator : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} - - StringRef getName() const { return getStringField(1); } - int64_t getEnumValue() const { return getInt64Field(2); } - bool Verify() const; - }; - - /// DIScope - A base class for various scopes. - class DIScope : public DIDescriptor { - protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {} - - /// Gets the parent scope for this scope node or returns a - /// default constructed scope. - DIScope getContext() const; - StringRef getFilename() const; - StringRef getDirectory() const; - }; - - /// DIType - This is a wrapper for a type. - /// FIXME: Types should be factored much better so that CV qualifiers and - /// others do not require a huge and empty descriptor full of zeros. - class DIType : public DIScope { - protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - - public: - DIType(const MDNode *N = 0) : DIScope(N) {} - - /// Verify - Verify that a type descriptor is well formed. - bool Verify() const; - - DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - uint64_t getSizeInBits() const { return getUInt64Field(5); } - uint64_t getAlignInBits() const { return getUInt64Field(6); } - // FIXME: Offset is only used for DW_TAG_member nodes. Making every type - // carry this is just plain insane. - uint64_t getOffsetInBits() const { return getUInt64Field(7); } - unsigned getFlags() const { return getUnsignedField(8); } - bool isPrivate() const { - return (getFlags() & FlagPrivate) != 0; - } - bool isProtected() const { - return (getFlags() & FlagProtected) != 0; - } - bool isForwardDecl() const { - return (getFlags() & FlagFwdDecl) != 0; - } - // isAppleBlock - Return true if this is the Apple Blocks extension. - bool isAppleBlockExtension() const { - return (getFlags() & FlagAppleBlock) != 0; - } - bool isBlockByrefStruct() const { - return (getFlags() & FlagBlockByrefStruct) != 0; - } - bool isVirtual() const { - return (getFlags() & FlagVirtual) != 0; - } - bool isArtificial() const { - return (getFlags() & FlagArtificial) != 0; - } - bool isObjectPointer() const { - return (getFlags() & FlagObjectPointer) != 0; - } - bool isObjcClassComplete() const { - return (getFlags() & FlagObjcClassComplete) != 0; - } - bool isVector() const { - return (getFlags() & FlagVector) != 0; - } - bool isStaticMember() const { - return (getFlags() & FlagStaticMember) != 0; - } - bool isValid() const { - return DbgNode && isType(); - } - - /// isUnsignedDIType - Return true if type encoding is unsigned. - bool isUnsignedDIType(); - - /// replaceAllUsesWith - Replace all uses of debug info referenced by - /// this descriptor. - void replaceAllUsesWith(DIDescriptor &D); - void replaceAllUsesWith(MDNode *D); - }; - - /// DIBasicType - A basic type, like 'int' or 'float'. - class DIBasicType : public DIType { - public: - explicit DIBasicType(const MDNode *N = 0) : DIType(N) {} - - unsigned getEncoding() const { return getUnsignedField(9); } - - /// Verify - Verify that a basic type descriptor is well formed. - bool Verify() const; - }; - - /// DIDerivedType - A simple derived type, like a const qualified type, - /// a typedef, a pointer or reference, et cetera. Or, a data member of - /// a class/struct/union. - class DIDerivedType : public DIType { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - - public: - explicit DIDerivedType(const MDNode *N = 0) : DIType(N) {} - - DIType getTypeDerivedFrom() const { return getFieldAs<DIType>(9); } - - /// getOriginalTypeSize - If this type is derived from a base type then - /// return base type size. - uint64_t getOriginalTypeSize() const; - - /// getObjCProperty - Return property node, if this ivar is - /// associated with one. - MDNode *getObjCProperty() const; - - DIType getClassType() const { - assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs<DIType>(10); - } - - Constant *getConstant() const { - assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(10); - } - - /// Verify - Verify that a derived type descriptor is well formed. - bool Verify() const; - }; - - /// DICompositeType - This descriptor holds a type that can refer to multiple - /// other types, like a function or struct. - /// DICompositeType is derived from DIDerivedType because some - /// composite types (such as enums) can be derived from basic types - // FIXME: Make this derive from DIType directly & just store the - // base type in a single DIType field. - class DICompositeType : public DIDerivedType { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DICompositeType(const MDNode *N = 0) : DIDerivedType(N) {} - - DIArray getTypeArray() const { return getFieldAs<DIArray>(10); } - void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); - unsigned getRunTimeLang() const { return getUnsignedField(11); } - DICompositeType getContainingType() const { - return getFieldAs<DICompositeType>(12); - } - void setContainingType(DICompositeType ContainingType); - DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); } - - /// Verify - Verify that a composite type descriptor is well formed. - bool Verify() const; - }; - - /// DIFile - This is a wrapper for a file. - class DIFile : public DIScope { - friend class DIDescriptor; - public: - explicit DIFile(const MDNode *N = 0) : DIScope(N) {} - MDNode *getFileNode() const; - bool Verify() const; - }; - - /// DICompileUnit - A wrapper for a compile unit. - class DICompileUnit : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} - - unsigned getLanguage() const { return getUnsignedField(2); } - StringRef getProducer() const { return getStringField(3); } - - bool isOptimized() const { return getUnsignedField(4) != 0; } - StringRef getFlags() const { return getStringField(5); } - unsigned getRunTimeVersion() const { return getUnsignedField(6); } - - DIArray getEnumTypes() const; - DIArray getRetainedTypes() const; - DIArray getSubprograms() const; - DIArray getGlobalVariables() const; - DIArray getImportedEntities() const; - - StringRef getSplitDebugFilename() const { return getStringField(12); } - - /// Verify - Verify that a compile unit is well formed. - bool Verify() const; - }; - - /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). - class DISubprogram : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} - - DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - unsigned getLineNumber() const { return getUnsignedField(6); } - DICompositeType getType() const { return getFieldAs<DICompositeType>(7); } - - /// isLocalToUnit - Return true if this subprogram is local to the current - /// compile unit, like 'static' in C. - unsigned isLocalToUnit() const { return getUnsignedField(8); } - unsigned isDefinition() const { return getUnsignedField(9); } - - unsigned getVirtuality() const { return getUnsignedField(10); } - unsigned getVirtualIndex() const { return getUnsignedField(11); } - - DICompositeType getContainingType() const { - return getFieldAs<DICompositeType>(12); - } - - unsigned getFlags() const { - return getUnsignedField(13); - } - - unsigned isArtificial() const { - return (getUnsignedField(13) & FlagArtificial) != 0; - } - /// isPrivate - Return true if this subprogram has "private" - /// access specifier. - bool isPrivate() const { - return (getUnsignedField(13) & FlagPrivate) != 0; - } - /// isProtected - Return true if this subprogram has "protected" - /// access specifier. - bool isProtected() const { - return (getUnsignedField(13) & FlagProtected) != 0; - } - /// isExplicit - Return true if this subprogram is marked as explicit. - bool isExplicit() const { - return (getUnsignedField(13) & FlagExplicit) != 0; - } - /// isPrototyped - Return true if this subprogram is prototyped. - bool isPrototyped() const { - return (getUnsignedField(13) & FlagPrototyped) != 0; - } - - unsigned isOptimized() const; - - /// Verify - Verify that a subprogram descriptor is well formed. - bool Verify() const; - - /// describes - Return true if this subprogram provides debugging - /// information for the function F. - bool describes(const Function *F); - - Function *getFunction() const { return getFunctionField(15); } - void replaceFunction(Function *F) { replaceFunctionField(15, F); } - DIArray getTemplateParams() const { return getFieldAs<DIArray>(16); } - DISubprogram getFunctionDeclaration() const { - return getFieldAs<DISubprogram>(17); - } - MDNode *getVariablesNodes() const; - DIArray getVariables() const; - - /// getScopeLineNumber - Get the beginning of the scope of the - /// function, not necessarily where the name of the program - /// starts. - unsigned getScopeLineNumber() const { return getUnsignedField(19); } - }; - - /// DILexicalBlock - This is a wrapper for a lexical block. - class DILexicalBlock : public DIScope { - public: - explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - unsigned getColumnNumber() const { return getUnsignedField(4); } - bool Verify() const; - }; - - /// DILexicalBlockFile - This is a wrapper for a lexical block with - /// a filename change. - class DILexicalBlockFile : public DIScope { - public: - explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { - if (getScope().isSubprogram()) - return getScope(); - return getScope().getContext(); - } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } - bool Verify() const; - }; - - /// DINameSpace - A wrapper for a C++ style name space. - class DINameSpace : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - bool Verify() const; - }; - - /// DITemplateTypeParameter - This is a wrapper for template type parameter. - class DITemplateTypeParameter : public DIDescriptor { - public: - explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - DIType getType() const { return getFieldAs<DIType>(3); } - StringRef getFilename() const { - return getFieldAs<DIFile>(4).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs<DIFile>(4).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(5); } - unsigned getColumnNumber() const { return getUnsignedField(6); } - bool Verify() const; - }; - - /// DITemplateValueParameter - This is a wrapper for template value parameter. - class DITemplateValueParameter : public DIDescriptor { - public: - explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - DIType getType() const { return getFieldAs<DIType>(3); } - Value *getValue() const; - StringRef getFilename() const { - return getFieldAs<DIFile>(5).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs<DIFile>(5).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(6); } - unsigned getColumnNumber() const { return getUnsignedField(7); } - bool Verify() const; - }; - - /// DIGlobalVariable - This is a wrapper for a global variable. - class DIGlobalVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIGlobalVariable(const MDNode *N = 0) : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - StringRef getFilename() const { - return getFieldAs<DIFile>(6).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs<DIFile>(6).getDirectory(); - - } - - unsigned getLineNumber() const { return getUnsignedField(7); } - DIType getType() const { return getFieldAs<DIType>(8); } - unsigned isLocalToUnit() const { return getUnsignedField(9); } - unsigned isDefinition() const { return getUnsignedField(10); } - - GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } - Constant *getConstant() const { return getConstantField(11); } - DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs<DIDerivedType>(12); - } - - /// Verify - Verify that a global variable descriptor is well formed. - bool Verify() const; - }; - - /// DIVariable - This is a wrapper for a variable (e.g. parameter, local, - /// global etc). - class DIVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIVariable(const MDNode *N = 0) : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - DIFile getFile() const { return getFieldAs<DIFile>(3); } - unsigned getLineNumber() const { - return (getUnsignedField(4) << 8) >> 8; - } - unsigned getArgNumber() const { - unsigned L = getUnsignedField(4); - return L >> 24; - } - DIType getType() const { return getFieldAs<DIType>(5); } - - /// isArtificial - Return true if this variable is marked as "artificial". - bool isArtificial() const { - return (getUnsignedField(6) & FlagArtificial) != 0; - } - - bool isObjectPointer() const { - return (getUnsignedField(6) & FlagObjectPointer) != 0; - } - - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getUnsignedField(6) & FlagIndirectVariable) != 0; - } - - /// getInlinedAt - If this variable is inlined then return inline location. - MDNode *getInlinedAt() const; - - /// Verify - Verify that a variable descriptor is well formed. - bool Verify() const; - - /// HasComplexAddr - Return true if the variable has a complex address. - bool hasComplexAddress() const { - return getNumAddrElements() > 0; - } - - unsigned getNumAddrElements() const; - - uint64_t getAddrElement(unsigned Idx) const { - return getUInt64Field(Idx+8); - } - - /// isBlockByrefVariable - Return true if the variable was declared as - /// a "__block" variable (Apple Blocks). - bool isBlockByrefVariable() const { - return getType().isBlockByrefStruct(); - } - - /// isInlinedFnArgument - Return true if this variable provides debugging - /// information for an inlined function arguments. - bool isInlinedFnArgument(const Function *CurFn); - - void printExtendedName(raw_ostream &OS) const; - }; - - /// DILocation - This object holds location information. This object - /// is not associated with any DWARF tag. - class DILocation : public DIDescriptor { - public: - explicit DILocation(const MDNode *N) : DIDescriptor(N) { } - - unsigned getLineNumber() const { return getUnsignedField(0); } - unsigned getColumnNumber() const { return getUnsignedField(1); } - DIScope getScope() const { return getFieldAs<DIScope>(2); } - DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); } - StringRef getFilename() const { return getScope().getFilename(); } - StringRef getDirectory() const { return getScope().getDirectory(); } - bool Verify() const; - }; - - class DIObjCProperty : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) { } - - StringRef getObjCPropertyName() const { return getStringField(1); } - DIFile getFile() const { return getFieldAs<DIFile>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - - StringRef getObjCPropertyGetterName() const { - return getStringField(4); - } - StringRef getObjCPropertySetterName() const { - return getStringField(5); - } - bool isReadOnlyObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; - } - bool isReadWriteObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; - } - bool isAssignObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; - } - bool isRetainObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; - } - bool isCopyObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; - } - bool isNonAtomicObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; - } - - DIType getType() const { return getFieldAs<DIType>(7); } - - /// Verify - Verify that a derived type descriptor is well formed. - bool Verify() const; - }; - - /// \brief An imported module (C++ using directive or similar). - class DIImportedEntity : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) { } - DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIDescriptor getEntity() const { return getFieldAs<DIDescriptor>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - StringRef getName() const { return getStringField(4); } - bool Verify() const; - }; - - /// getDISubprogram - Find subprogram that is enclosing this scope. - DISubprogram getDISubprogram(const MDNode *Scope); - - /// getDICompositeType - Find underlying composite type. - DICompositeType getDICompositeType(DIType T); - - /// isSubprogramContext - Return true if Context is either a subprogram - /// or another context nested inside a subprogram. - bool isSubprogramContext(const MDNode *Context); - - /// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable - /// to hold function specific information. - NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); - - /// getFnSpecificMDNode - Return a NameMDNode, if available, that is - /// suitable to hold function specific information. - NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); - - /// createInlinedVariable - Create a new inlined variable based on current - /// variable. - /// @param DV Current Variable. - /// @param InlinedScope Location at current variable is inlined. - DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext); - - /// cleanseInlinedVariable - Remove inlined scope from the variable. - DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); - - /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To - /// list debug info MDNodes used by an instruction, DebugInfoFinder uses - /// processDeclare, processValue and processLocation to handle DbgDeclareInst, - /// DbgValueInst and DbgLoc attached to instructions. processModule will go - /// through all DICompileUnits in llvm.dbg.cu and list debug info MDNodes - /// used by the CUs. - class DebugInfoFinder { - public: - /// processModule - Process entire module and collect debug info - /// anchors. - void processModule(const Module &M); - - /// processDeclare - Process DbgDeclareInst. - void processDeclare(const DbgDeclareInst *DDI); - /// Process DbgValueInst. - void processValue(const DbgValueInst *DVI); - /// processLocation - Process DILocation. - void processLocation(DILocation Loc); - - /// Clear all lists. - void reset(); - private: - /// processType - Process DIType. - void processType(DIType DT); - - /// processLexicalBlock - Process DILexicalBlock. - void processLexicalBlock(DILexicalBlock LB); - - /// processSubprogram - Process DISubprogram. - void processSubprogram(DISubprogram SP); - - void processScope(DIScope Scope); - - /// addCompileUnit - Add compile unit into CUs. - bool addCompileUnit(DICompileUnit CU); - - /// addGlobalVariable - Add global variable into GVs. - bool addGlobalVariable(DIGlobalVariable DIG); - - // addSubprogram - Add subprogram into SPs. - bool addSubprogram(DISubprogram SP); - - /// addType - Add type into Tys. - bool addType(DIType DT); - - bool addScope(DIScope Scope); - - public: - typedef SmallVectorImpl<MDNode *>::const_iterator iterator; - iterator compile_unit_begin() const { return CUs.begin(); } - iterator compile_unit_end() const { return CUs.end(); } - iterator subprogram_begin() const { return SPs.begin(); } - iterator subprogram_end() const { return SPs.end(); } - iterator global_variable_begin() const { return GVs.begin(); } - iterator global_variable_end() const { return GVs.end(); } - iterator type_begin() const { return TYs.begin(); } - iterator type_end() const { return TYs.end(); } - iterator scope_begin() const { return Scopes.begin(); } - iterator scope_end() const { return Scopes.end(); } - - unsigned compile_unit_count() const { return CUs.size(); } - unsigned global_variable_count() const { return GVs.size(); } - unsigned subprogram_count() const { return SPs.size(); } - unsigned type_count() const { return TYs.size(); } - unsigned scope_count() const { return Scopes.size(); } - - private: - SmallVector<MDNode *, 8> CUs; // Compile Units - SmallVector<MDNode *, 8> SPs; // Subprograms - SmallVector<MDNode *, 8> GVs; // Global Variables; - SmallVector<MDNode *, 8> TYs; // Types - SmallVector<MDNode *, 8> Scopes; // Scopes - SmallPtrSet<MDNode *, 64> NodesSeen; - }; +protected: + const MDNode *DbgNode; + + StringRef getStringField(unsigned Elt) const; + unsigned getUnsignedField(unsigned Elt) const { + return (unsigned)getUInt64Field(Elt); + } + uint64_t getUInt64Field(unsigned Elt) const; + int64_t getInt64Field(unsigned Elt) const; + DIDescriptor getDescriptorField(unsigned Elt) const; + + template <typename DescTy> DescTy getFieldAs(unsigned Elt) const { + return DescTy(getDescriptorField(Elt)); + } + + GlobalVariable *getGlobalVariableField(unsigned Elt) const; + Constant *getConstantField(unsigned Elt) const; + Function *getFunctionField(unsigned Elt) const; + void replaceFunctionField(unsigned Elt, Function *F); + +public: + explicit DIDescriptor(const MDNode *N = 0) : DbgNode(N) {} + + bool Verify() const; + + operator MDNode *() const { return const_cast<MDNode *>(DbgNode); } + MDNode *operator->() const { return const_cast<MDNode *>(DbgNode); } + + // An explicit operator bool so that we can do testing of DI values + // easily. + // FIXME: This operator bool isn't actually protecting anything at the + // moment due to the conversion operator above making DIDescriptor nodes + // implicitly convertable to bool. + LLVM_EXPLICIT operator bool() const { return DbgNode != 0; } + + bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } + bool operator!=(DIDescriptor Other) const { return !operator==(Other); } + + uint16_t getTag() const { + return getUnsignedField(0) & ~LLVMDebugVersionMask; + } + + bool isDerivedType() const; + bool isCompositeType() const; + bool isBasicType() const; + bool isVariable() const; + bool isSubprogram() const; + bool isGlobalVariable() const; + bool isScope() const; + bool isFile() const; + bool isCompileUnit() const; + bool isNameSpace() const; + bool isLexicalBlockFile() const; + bool isLexicalBlock() const; + bool isSubrange() const; + bool isEnumerator() const; + bool isType() const; + bool isUnspecifiedParameter() const; + bool isTemplateTypeParameter() const; + bool isTemplateValueParameter() const; + bool isObjCProperty() const; + bool isImportedEntity() const; + + /// print - print descriptor. + void print(raw_ostream &OS) const; + + /// dump - print descriptor to dbgs() with a newline. + void dump() const; +}; + +/// DISubrange - This is used to represent ranges, for array bounds. +class DISubrange : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} + + int64_t getLo() const { return getInt64Field(1); } + int64_t getCount() const { return getInt64Field(2); } + bool Verify() const; +}; + +/// DIArray - This descriptor holds an array of descriptors. +class DIArray : public DIDescriptor { +public: + explicit DIArray(const MDNode *N = 0) : DIDescriptor(N) {} + + unsigned getNumElements() const; + DIDescriptor getElement(unsigned Idx) const { + return getDescriptorField(Idx); + } +}; + +/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). +/// FIXME: it seems strange that this doesn't have either a reference to the +/// type/precision or a file/line pair for location info. +class DIEnumerator : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} + + StringRef getName() const { return getStringField(1); } + int64_t getEnumValue() const { return getInt64Field(2); } + bool Verify() const; +}; + +template <typename T> class DIRef; +typedef DIRef<DIScope> DIScopeRef; +typedef DIRef<DIType> DITypeRef; + +/// DIScope - A base class for various scopes. +class DIScope : public DIDescriptor { +protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIScope(const MDNode *N = 0) : DIDescriptor(N) {} + + /// Gets the parent scope for this scope node or returns a + /// default constructed scope. + DIScopeRef getContext() const; + /// If the scope node has a name, return that, else return an empty string. + StringRef getName() const; + StringRef getFilename() const; + StringRef getDirectory() const; + + /// Generate a reference to this DIScope. Uses the type identifier instead + /// of the actual MDNode if possible, to help type uniquing. + DIScopeRef getRef() const; +}; + +/// Represents reference to a DIDescriptor, abstracts over direct and +/// identifier-based metadata references. +template <typename T> class DIRef { + template <typename DescTy> + friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; + friend DIScopeRef DIScope::getContext() const; + friend DIScopeRef DIScope::getRef() const; + + /// Val can be either a MDNode or a MDString, in the latter, + /// MDString specifies the type identifier. + const Value *Val; + explicit DIRef(const Value *V); + +public: + T resolve(const DITypeIdentifierMap &Map) const; + StringRef getName() const; + operator Value *() const { return const_cast<Value *>(Val); } +}; + +template <typename T> +T DIRef<T>::resolve(const DITypeIdentifierMap &Map) const { + if (!Val) + return T(); + + if (const MDNode *MD = dyn_cast<MDNode>(Val)) + return T(MD); + + const MDString *MS = cast<MDString>(Val); + // Find the corresponding MDNode. + DITypeIdentifierMap::const_iterator Iter = Map.find(MS); + assert(Iter != Map.end() && "Identifier not in the type map?"); + assert(DIDescriptor(Iter->second).isType() && + "MDNode in DITypeIdentifierMap should be a DIType."); + return T(Iter->second); +} + +template <typename T> StringRef DIRef<T>::getName() const { + if (!Val) + return StringRef(); + + if (const MDNode *MD = dyn_cast<MDNode>(Val)) + return T(MD).getName(); + + const MDString *MS = cast<MDString>(Val); + return MS->getString(); +} + +/// Specialize getFieldAs to handle fields that are references to DIScopes. +template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const; +/// Specialize DIRef constructor for DIScopeRef. +template <> DIRef<DIScope>::DIRef(const Value *V); + +/// Specialize getFieldAs to handle fields that are references to DITypes. +template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; +/// Specialize DIRef constructor for DITypeRef. +template <> DIRef<DIType>::DIRef(const Value *V); + +/// DIType - This is a wrapper for a type. +/// FIXME: Types should be factored much better so that CV qualifiers and +/// others do not require a huge and empty descriptor full of zeros. +class DIType : public DIScope { +protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIType(const MDNode *N = 0) : DIScope(N) {} + + /// Verify - Verify that a type descriptor is well formed. + bool Verify() const; + + DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } + StringRef getName() const { return getStringField(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + uint64_t getSizeInBits() const { return getUInt64Field(5); } + uint64_t getAlignInBits() const { return getUInt64Field(6); } + // FIXME: Offset is only used for DW_TAG_member nodes. Making every type + // carry this is just plain insane. + uint64_t getOffsetInBits() const { return getUInt64Field(7); } + unsigned getFlags() const { return getUnsignedField(8); } + bool isPrivate() const { return (getFlags() & FlagPrivate) != 0; } + bool isProtected() const { return (getFlags() & FlagProtected) != 0; } + bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } + // isAppleBlock - Return true if this is the Apple Blocks extension. + bool isAppleBlockExtension() const { + return (getFlags() & FlagAppleBlock) != 0; + } + bool isBlockByrefStruct() const { + return (getFlags() & FlagBlockByrefStruct) != 0; + } + bool isVirtual() const { return (getFlags() & FlagVirtual) != 0; } + bool isArtificial() const { return (getFlags() & FlagArtificial) != 0; } + bool isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; } + bool isObjcClassComplete() const { + return (getFlags() & FlagObjcClassComplete) != 0; + } + bool isVector() const { return (getFlags() & FlagVector) != 0; } + bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; } + bool isValid() const { return DbgNode && isType(); } + + /// replaceAllUsesWith - Replace all uses of debug info referenced by + /// this descriptor. + void replaceAllUsesWith(DIDescriptor &D); + void replaceAllUsesWith(MDNode *D); +}; + +/// DIBasicType - A basic type, like 'int' or 'float'. +class DIBasicType : public DIType { +public: + explicit DIBasicType(const MDNode *N = 0) : DIType(N) {} + + unsigned getEncoding() const { return getUnsignedField(9); } + + /// Verify - Verify that a basic type descriptor is well formed. + bool Verify() const; +}; + +/// DIDerivedType - A simple derived type, like a const qualified type, +/// a typedef, a pointer or reference, et cetera. Or, a data member of +/// a class/struct/union. +class DIDerivedType : public DIType { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIDerivedType(const MDNode *N = 0) : DIType(N) {} + + DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(9); } + + /// getObjCProperty - Return property node, if this ivar is + /// associated with one. + MDNode *getObjCProperty() const; + + DITypeRef getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return getFieldAs<DITypeRef>(10); + } + + Constant *getConstant() const { + assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); + return getConstantField(10); + } + + /// Verify - Verify that a derived type descriptor is well formed. + bool Verify() const; +}; + +/// DICompositeType - This descriptor holds a type that can refer to multiple +/// other types, like a function or struct. +/// DICompositeType is derived from DIDerivedType because some +/// composite types (such as enums) can be derived from basic types +// FIXME: Make this derive from DIType directly & just store the +// base type in a single DIType field. +class DICompositeType : public DIDerivedType { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DICompositeType(const MDNode *N = 0) : DIDerivedType(N) {} + + DIArray getTypeArray() const { return getFieldAs<DIArray>(10); } + void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); + void addMember(DIDescriptor D); + unsigned getRunTimeLang() const { return getUnsignedField(11); } + DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); } + void setContainingType(DICompositeType ContainingType); + DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); } + MDString *getIdentifier() const; + + /// Verify - Verify that a composite type descriptor is well formed. + bool Verify() const; +}; + +/// DIFile - This is a wrapper for a file. +class DIFile : public DIScope { + friend class DIDescriptor; + +public: + explicit DIFile(const MDNode *N = 0) : DIScope(N) {} + MDNode *getFileNode() const; + bool Verify() const; +}; + +/// DICompileUnit - A wrapper for a compile unit. +class DICompileUnit : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} + + unsigned getLanguage() const { return getUnsignedField(2); } + StringRef getProducer() const { return getStringField(3); } + + bool isOptimized() const { return getUnsignedField(4) != 0; } + StringRef getFlags() const { return getStringField(5); } + unsigned getRunTimeVersion() const { return getUnsignedField(6); } + + DIArray getEnumTypes() const; + DIArray getRetainedTypes() const; + DIArray getSubprograms() const; + DIArray getGlobalVariables() const; + DIArray getImportedEntities() const; + + StringRef getSplitDebugFilename() const { return getStringField(12); } + + /// Verify - Verify that a compile unit is well formed. + bool Verify() const; +}; + +/// DISubprogram - This is a wrapper for a subprogram (e.g. a function). +class DISubprogram : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} + + DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + unsigned getLineNumber() const { return getUnsignedField(6); } + DICompositeType getType() const { return getFieldAs<DICompositeType>(7); } + + /// isLocalToUnit - Return true if this subprogram is local to the current + /// compile unit, like 'static' in C. + unsigned isLocalToUnit() const { return getUnsignedField(8); } + unsigned isDefinition() const { return getUnsignedField(9); } + + unsigned getVirtuality() const { return getUnsignedField(10); } + unsigned getVirtualIndex() const { return getUnsignedField(11); } + + DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); } + + unsigned getFlags() const { return getUnsignedField(13); } + + unsigned isArtificial() const { + return (getUnsignedField(13) & FlagArtificial) != 0; + } + /// isPrivate - Return true if this subprogram has "private" + /// access specifier. + bool isPrivate() const { return (getUnsignedField(13) & FlagPrivate) != 0; } + /// isProtected - Return true if this subprogram has "protected" + /// access specifier. + bool isProtected() const { + return (getUnsignedField(13) & FlagProtected) != 0; + } + /// isExplicit - Return true if this subprogram is marked as explicit. + bool isExplicit() const { return (getUnsignedField(13) & FlagExplicit) != 0; } + /// isPrototyped - Return true if this subprogram is prototyped. + bool isPrototyped() const { + return (getUnsignedField(13) & FlagPrototyped) != 0; + } + + unsigned isOptimized() const; + + /// Verify - Verify that a subprogram descriptor is well formed. + bool Verify() const; + + /// describes - Return true if this subprogram provides debugging + /// information for the function F. + bool describes(const Function *F); + + Function *getFunction() const { return getFunctionField(15); } + void replaceFunction(Function *F) { replaceFunctionField(15, F); } + DIArray getTemplateParams() const { return getFieldAs<DIArray>(16); } + DISubprogram getFunctionDeclaration() const { + return getFieldAs<DISubprogram>(17); + } + MDNode *getVariablesNodes() const; + DIArray getVariables() const; + + /// getScopeLineNumber - Get the beginning of the scope of the + /// function, not necessarily where the name of the program + /// starts. + unsigned getScopeLineNumber() const { return getUnsignedField(19); } +}; + +/// DILexicalBlock - This is a wrapper for a lexical block. +class DILexicalBlock : public DIScope { +public: + explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs<DIScope>(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + unsigned getColumnNumber() const { return getUnsignedField(4); } + bool Verify() const; +}; + +/// DILexicalBlockFile - This is a wrapper for a lexical block with +/// a filename change. +class DILexicalBlockFile : public DIScope { +public: + explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { + if (getScope().isSubprogram()) + return getScope(); + return getScope().getContext(); + } + unsigned getLineNumber() const { return getScope().getLineNumber(); } + unsigned getColumnNumber() const { return getScope().getColumnNumber(); } + DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } + bool Verify() const; +}; + +/// DINameSpace - A wrapper for a C++ style name space. +class DINameSpace : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs<DIScope>(2); } + StringRef getName() const { return getStringField(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + bool Verify() const; +}; + +/// DITemplateTypeParameter - This is a wrapper for template type parameter. +class DITemplateTypeParameter : public DIDescriptor { +public: + explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } + StringRef getName() const { return getStringField(2); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } + StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); } + StringRef getDirectory() const { + return getFieldAs<DIFile>(4).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(5); } + unsigned getColumnNumber() const { return getUnsignedField(6); } + bool Verify() const; +}; + +/// DITemplateValueParameter - This is a wrapper for template value parameter. +class DITemplateValueParameter : public DIDescriptor { +public: + explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } + StringRef getName() const { return getStringField(2); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } + Value *getValue() const; + StringRef getFilename() const { return getFieldAs<DIFile>(5).getFilename(); } + StringRef getDirectory() const { + return getFieldAs<DIFile>(5).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(6); } + unsigned getColumnNumber() const { return getUnsignedField(7); } + bool Verify() const; +}; + +/// DIGlobalVariable - This is a wrapper for a global variable. +class DIGlobalVariable : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIGlobalVariable(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + StringRef getFilename() const { return getFieldAs<DIFile>(6).getFilename(); } + StringRef getDirectory() const { + return getFieldAs<DIFile>(6).getDirectory(); + } + + unsigned getLineNumber() const { return getUnsignedField(7); } + DIType getType() const { return getFieldAs<DIType>(8); } + unsigned isLocalToUnit() const { return getUnsignedField(9); } + unsigned isDefinition() const { return getUnsignedField(10); } + + GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } + Constant *getConstant() const { return getConstantField(11); } + DIDerivedType getStaticDataMemberDeclaration() const { + return getFieldAs<DIDerivedType>(12); + } + + /// Verify - Verify that a global variable descriptor is well formed. + bool Verify() const; +}; + +/// DIVariable - This is a wrapper for a variable (e.g. parameter, local, +/// global etc). +class DIVariable : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIVariable(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getName() const { return getStringField(2); } + DIFile getFile() const { return getFieldAs<DIFile>(3); } + unsigned getLineNumber() const { return (getUnsignedField(4) << 8) >> 8; } + unsigned getArgNumber() const { + unsigned L = getUnsignedField(4); + return L >> 24; + } + DIType getType() const { return getFieldAs<DIType>(5); } + + /// isArtificial - Return true if this variable is marked as "artificial". + bool isArtificial() const { + return (getUnsignedField(6) & FlagArtificial) != 0; + } + + bool isObjectPointer() const { + return (getUnsignedField(6) & FlagObjectPointer) != 0; + } + + /// \brief Return true if this variable is represented as a pointer. + bool isIndirect() const { + return (getUnsignedField(6) & FlagIndirectVariable) != 0; + } + + /// getInlinedAt - If this variable is inlined then return inline location. + MDNode *getInlinedAt() const; + + /// Verify - Verify that a variable descriptor is well formed. + bool Verify() const; + + /// HasComplexAddr - Return true if the variable has a complex address. + bool hasComplexAddress() const { return getNumAddrElements() > 0; } + + unsigned getNumAddrElements() const; + + uint64_t getAddrElement(unsigned Idx) const { + return getUInt64Field(Idx + 8); + } + + /// isBlockByrefVariable - Return true if the variable was declared as + /// a "__block" variable (Apple Blocks). + bool isBlockByrefVariable() const { return getType().isBlockByrefStruct(); } + + /// isInlinedFnArgument - Return true if this variable provides debugging + /// information for an inlined function arguments. + bool isInlinedFnArgument(const Function *CurFn); + + void printExtendedName(raw_ostream &OS) const; +}; + +/// DILocation - This object holds location information. This object +/// is not associated with any DWARF tag. +class DILocation : public DIDescriptor { +public: + explicit DILocation(const MDNode *N) : DIDescriptor(N) {} + + unsigned getLineNumber() const { return getUnsignedField(0); } + unsigned getColumnNumber() const { return getUnsignedField(1); } + DIScope getScope() const { return getFieldAs<DIScope>(2); } + DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); } + StringRef getFilename() const { return getScope().getFilename(); } + StringRef getDirectory() const { return getScope().getDirectory(); } + bool Verify() const; +}; + +class DIObjCProperty : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} + + StringRef getObjCPropertyName() const { return getStringField(1); } + DIFile getFile() const { return getFieldAs<DIFile>(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + + StringRef getObjCPropertyGetterName() const { return getStringField(4); } + StringRef getObjCPropertySetterName() const { return getStringField(5); } + bool isReadOnlyObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; + } + bool isReadWriteObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; + } + bool isAssignObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; + } + bool isRetainObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; + } + bool isCopyObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; + } + bool isNonAtomicObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; + } + + DIType getType() const { return getFieldAs<DIType>(7); } + + /// Verify - Verify that a derived type descriptor is well formed. + bool Verify() const; +}; + +/// \brief An imported module (C++ using directive or similar). +class DIImportedEntity : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} + DIScope getContext() const { return getFieldAs<DIScope>(1); } + DIDescriptor getEntity() const { return getFieldAs<DIDescriptor>(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + StringRef getName() const { return getStringField(4); } + bool Verify() const; +}; + +/// getDISubprogram - Find subprogram that is enclosing this scope. +DISubprogram getDISubprogram(const MDNode *Scope); + +/// getDICompositeType - Find underlying composite type. +DICompositeType getDICompositeType(DIType T); + +/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable +/// to hold function specific information. +NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); + +/// getFnSpecificMDNode - Return a NameMDNode, if available, that is +/// suitable to hold function specific information. +NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); + +/// createInlinedVariable - Create a new inlined variable based on current +/// variable. +/// @param DV Current Variable. +/// @param InlinedScope Location at current variable is inlined. +DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, + LLVMContext &VMContext); + +/// cleanseInlinedVariable - Remove inlined scope from the variable. +DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); + +/// Construct DITypeIdentifierMap by going through retained types of each CU. +DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); + +/// Strip debug info in the module if it exists. +/// To do this, we remove all calls to the debugger intrinsics and any named +/// metadata for debugging. We also remove debug locations for instructions. +/// Return true if module is modified. +bool StripDebugInfo(Module &M); + +/// Return Debug Info Metadata Version by checking module flags. +unsigned getDebugMetadataVersionFromModule(const Module &M); + +/// DebugInfoFinder tries to list all debug info MDNodes used in a module. To +/// list debug info MDNodes used by an instruction, DebugInfoFinder uses +/// processDeclare, processValue and processLocation to handle DbgDeclareInst, +/// DbgValueInst and DbgLoc attached to instructions. processModule will go +/// through all DICompileUnits in llvm.dbg.cu and list debug info MDNodes +/// used by the CUs. +class DebugInfoFinder { +public: + DebugInfoFinder() : TypeMapInitialized(false) {} + + /// processModule - Process entire module and collect debug info + /// anchors. + void processModule(const Module &M); + + /// processDeclare - Process DbgDeclareInst. + void processDeclare(const Module &M, const DbgDeclareInst *DDI); + /// Process DbgValueInst. + void processValue(const Module &M, const DbgValueInst *DVI); + /// processLocation - Process DILocation. + void processLocation(const Module &M, DILocation Loc); + + /// Clear all lists. + void reset(); + +private: + /// Initialize TypeIdentifierMap. + void InitializeTypeMap(const Module &M); + + /// processType - Process DIType. + void processType(DIType DT); + + /// processLexicalBlock - Process DILexicalBlock. + void processLexicalBlock(DILexicalBlock LB); + + /// processSubprogram - Process DISubprogram. + void processSubprogram(DISubprogram SP); + + void processScope(DIScope Scope); + + /// addCompileUnit - Add compile unit into CUs. + bool addCompileUnit(DICompileUnit CU); + + /// addGlobalVariable - Add global variable into GVs. + bool addGlobalVariable(DIGlobalVariable DIG); + + // addSubprogram - Add subprogram into SPs. + bool addSubprogram(DISubprogram SP); + + /// addType - Add type into Tys. + bool addType(DIType DT); + + bool addScope(DIScope Scope); + +public: + typedef SmallVectorImpl<MDNode *>::const_iterator iterator; + iterator compile_unit_begin() const { return CUs.begin(); } + iterator compile_unit_end() const { return CUs.end(); } + iterator subprogram_begin() const { return SPs.begin(); } + iterator subprogram_end() const { return SPs.end(); } + iterator global_variable_begin() const { return GVs.begin(); } + iterator global_variable_end() const { return GVs.end(); } + iterator type_begin() const { return TYs.begin(); } + iterator type_end() const { return TYs.end(); } + iterator scope_begin() const { return Scopes.begin(); } + iterator scope_end() const { return Scopes.end(); } + + unsigned compile_unit_count() const { return CUs.size(); } + unsigned global_variable_count() const { return GVs.size(); } + unsigned subprogram_count() const { return SPs.size(); } + unsigned type_count() const { return TYs.size(); } + unsigned scope_count() const { return Scopes.size(); } + +private: + SmallVector<MDNode *, 8> CUs; // Compile Units + SmallVector<MDNode *, 8> SPs; // Subprograms + SmallVector<MDNode *, 8> GVs; // Global Variables; + SmallVector<MDNode *, 8> TYs; // Types + SmallVector<MDNode *, 8> Scopes; // Scopes + SmallPtrSet<MDNode *, 64> NodesSeen; + DITypeIdentifierMap TypeIdentifierMap; + /// Specify if TypeIdentifierMap is initialized. + bool TypeMapInitialized; +}; } // end namespace llvm #endif diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 4bb7c77..a1a4642 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -38,11 +38,10 @@ public: DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>"), Line(0), Column(0) {} - DILineInfo(const SmallString<16> &fileName, - const SmallString<16> &functionName, - uint32_t line, uint32_t column) - : FileName(fileName), FunctionName(functionName), - Line(line), Column(column) {} + DILineInfo(StringRef fileName, StringRef functionName, uint32_t line, + uint32_t column) + : FileName(fileName), FunctionName(functionName), Line(line), + Column(column) {} const char *getFileName() { return FileName.c_str(); } const char *getFunctionName() { return FunctionName.c_str(); } @@ -105,10 +104,14 @@ enum DIDumpType { DIDT_Frames, DIDT_Info, DIDT_InfoDwo, + DIDT_Types, DIDT_Line, DIDT_Loc, DIDT_Ranges, DIDT_Pubnames, + DIDT_Pubtypes, + DIDT_GnuPubnames, + DIDT_GnuPubtypes, DIDT_Str, DIDT_StrDwo, DIDT_StrOffsetsDwo diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h index eaaccfb..533d259 100644 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARFFormValue.h @@ -10,15 +10,31 @@ #ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H #define LLVM_DEBUGINFO_DWARFFORMVALUE_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/DataExtractor.h" namespace llvm { -class DWARFCompileUnit; +class DWARFUnit; class raw_ostream; class DWARFFormValue { public: + enum FormClass { + FC_Unknown, + FC_Address, + FC_Block, + FC_Constant, + FC_String, + FC_Flag, + FC_Reference, + FC_Indirect, + FC_SectionOffset, + FC_Exprloc + }; + +private: struct ValueType { ValueType() : data(NULL) { uval = 0; @@ -32,49 +48,36 @@ public: const uint8_t* data; }; - enum { - eValueTypeInvalid = 0, - eValueTypeUnsigned, - eValueTypeSigned, - eValueTypeCStr, - eValueTypeBlock - }; - -private: uint16_t Form; // Form for this value. ValueType Value; // Contains all data for the form. public: - DWARFFormValue(uint16_t form = 0) : Form(form) {} + DWARFFormValue(uint16_t Form = 0) : Form(Form) {} uint16_t getForm() const { return Form; } - const ValueType& value() const { return Value; } - void dump(raw_ostream &OS, const DWARFCompileUnit* cu) const; + bool isFormClass(FormClass FC) const; + + void dump(raw_ostream &OS, const DWARFUnit *U) const; bool extractValue(DataExtractor data, uint32_t *offset_ptr, - const DWARFCompileUnit *cu); + const DWARFUnit *u); bool isInlinedCStr() const { return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr; } - const uint8_t *BlockData() const; - uint64_t getReference(const DWARFCompileUnit* cu) const; - /// Resolve any compile unit specific references so that we don't need - /// the compile unit at a later time in order to work with the form - /// value. - bool resolveCompileUnitReferences(const DWARFCompileUnit* cu); - uint64_t getUnsigned() const { return Value.uval; } - int64_t getSigned() const { return Value.sval; } - const char *getAsCString(const DataExtractor *debug_str_data_ptr) const; - const char *getIndirectCString(const DataExtractor *, - const DataExtractor *) const; - uint64_t getIndirectAddress(const DataExtractor *, - const DWARFCompileUnit *) const; + /// getAsFoo functions below return the extracted value as Foo if only + /// DWARFFormValue has form class is suitable for representing Foo. + Optional<uint64_t> getAsReference(const DWARFUnit *U) const; + Optional<uint64_t> getAsUnsignedConstant() const; + Optional<const char *> getAsCString(const DWARFUnit *U) const; + Optional<uint64_t> getAsAddress(const DWARFUnit *U) const; + Optional<uint64_t> getAsSectionOffset() const; + bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, - const DWARFCompileUnit *cu) const; + const DWARFUnit *u) const; static bool skipValue(uint16_t form, DataExtractor debug_info_data, - uint32_t *offset_ptr, const DWARFCompileUnit *cu); - static bool isBlockForm(uint16_t form); - static bool isDataForm(uint16_t form); - static const uint8_t *getFixedFormSizes(uint8_t AddrSize, uint16_t Version); + uint32_t *offset_ptr, const DWARFUnit *u); + + static ArrayRef<uint8_t> getFixedFormSizes(uint8_t AddrSize, + uint16_t Version); }; } diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index ceac298..233084d 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -16,7 +16,6 @@ #define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #include "llvm-c/ExecutionEngine.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" @@ -153,17 +152,8 @@ protected: /// abort. void *(*LazyFunctionCreator)(const std::string &); - /// ExceptionTableRegister - If Exception Handling is set, the JIT will - /// register dwarf tables with this function. - typedef void (*EERegisterFn)(void*); - EERegisterFn ExceptionTableRegister; - EERegisterFn ExceptionTableDeregister; - /// This maps functions to their exception tables frames. - DenseMap<const Function*, void*> AllExceptionTables; - - public: - /// lock - This lock protects the ExecutionEngine, JIT, JITResolver and + /// lock - This lock protects the ExecutionEngine, MCJIT, JIT, JITResolver and /// JITEmitter classes. It must be held while changing the internal state of /// any of those classes. sys::Mutex lock; @@ -225,7 +215,7 @@ public: /// FindFunctionNamed - Search all of the active modules to find the one that /// defines FnName. This is very slow operation and shouldn't be used for /// general code. - Function *FindFunctionNamed(const char *FnName); + virtual Function *FindFunctionNamed(const char *FnName); /// runFunction - Execute the specified function with the specified arguments, /// and return the result. @@ -240,6 +230,11 @@ public: /// found, this function silently returns a null pointer. Otherwise, /// it prints a message to stderr and aborts. /// + /// This function is deprecated for the MCJIT execution engine. + /// + /// FIXME: the JIT and MCJIT interfaces should be disentangled or united + /// again, if possible. + /// virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) = 0; @@ -252,6 +247,23 @@ public: "EE!"); } + /// generateCodeForModule - Run code generationen for the specified module and + /// load it into memory. + /// + /// When this function has completed, all code and data for the specified + /// module, and any module on which this module depends, will be generated + /// and loaded into memory, but relocations will not yet have been applied + /// and all memory will be readable and writable but not executable. + /// + /// This function is primarily useful when generating code for an external + /// target, allowing the client an opportunity to remap section addresses + /// before relocations are applied. Clients that intend to execute code + /// locally can use the getFunctionAddress call, which will generate code + /// and apply final preparations all in one step. + /// + /// This method has no effect for the legacy JIT engine or the interpeter. + virtual void generateCodeForModule(Module *M) {} + /// finalizeObject - ensure the module is fully processed and is usable. /// /// It is the user-level function for completing the process of making the @@ -266,7 +278,7 @@ public: /// the static constructors or destructors for a program. /// /// \param isDtors - Run the destructors instead of constructors. - void runStaticConstructorsDestructors(bool isDtors); + virtual void runStaticConstructorsDestructors(bool isDtors); /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a particular module. @@ -307,10 +319,16 @@ public: /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. + /// + /// This function is deprecated for the MCJIT execution engine. It doesn't + /// seem to be needed in that case, but an equivalent can be added if it is. void *getPointerToGlobalIfAvailable(const GlobalValue *GV); /// getPointerToGlobal - This returns the address of the specified global /// value. This may involve code generation if it's a function. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. void *getPointerToGlobal(const GlobalValue *GV); /// getPointerToFunction - The different EE's represent function bodies in @@ -318,22 +336,48 @@ public: /// pointer should look like. When F is destroyed, the ExecutionEngine will /// remove its global mapping and free any machine code. Be sure no threads /// are running inside F when that happens. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunction(Function *F) = 0; /// getPointerToBasicBlock - The different EE's represent basic blocks in /// different ways. Return the representation for a blockaddress of the /// specified block. + /// + /// This function will not be implemented for the MCJIT execution engine. virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. See /// getPointerToFunction for the requirements on destroying F. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. return getPointerToFunction(F); } + /// getGlobalValueAddress - Return the address of the specified global + /// value. This may involve code generation. + /// + /// This function should not be called with the JIT or interpreter engines. + virtual uint64_t getGlobalValueAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToGlobal instead. + return 0; + } + + /// getFunctionAddress - Return the address of the specified function. + /// This may involve code generation. + virtual uint64_t getFunctionAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToFunction instead. + return 0; + } + // The JIT overrides a version that actually does this. virtual void runJITOnFunction(Function *, MachineCodeInfo * = 0) { } @@ -366,6 +410,9 @@ public: /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { return getPointerToGlobal((const GlobalValue *)GV); } @@ -435,41 +482,6 @@ public: LazyFunctionCreator = P; } - /// InstallExceptionTableRegister - The JIT will use the given function - /// to register the exception tables it generates. - void InstallExceptionTableRegister(EERegisterFn F) { - ExceptionTableRegister = F; - } - void InstallExceptionTableDeregister(EERegisterFn F) { - ExceptionTableDeregister = F; - } - - /// RegisterTable - Registers the given pointer as an exception table. It - /// uses the ExceptionTableRegister function. - void RegisterTable(const Function *fn, void* res) { - if (ExceptionTableRegister) { - ExceptionTableRegister(res); - AllExceptionTables[fn] = res; - } - } - - /// DeregisterTable - Deregisters the exception frame previously registered - /// for the given function. - void DeregisterTable(const Function *Fn) { - if (ExceptionTableDeregister) { - DenseMap<const Function*, void*>::iterator frame = - AllExceptionTables.find(Fn); - if(frame != AllExceptionTables.end()) { - ExceptionTableDeregister(frame->second); - AllExceptionTables.erase(frame); - } - } - } - - /// DeregisterAllTables - Deregisters all previously registered pointers to an - /// exception tables. It uses the ExceptionTableoDeregister function. - void DeregisterAllTables(); - protected: explicit ExecutionEngine(Module *M); diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h index 32de404..af2a926 100644 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ b/include/llvm/ExecutionEngine/ObjectBuffer.h @@ -30,6 +30,7 @@ namespace llvm { /// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the /// actual memory it points to. class ObjectBuffer { + virtual void anchor(); public: ObjectBuffer() {} ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {} @@ -56,6 +57,7 @@ protected: /// while providing a common ObjectBuffer interface for access to the /// memory once the object has been generated. class ObjectBufferStream : public ObjectBuffer { + virtual void anchor(); public: ObjectBufferStream() : OS(SV) {} virtual ~ObjectBufferStream() {} diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h index aa200fb..d1849df 100644 --- a/include/llvm/ExecutionEngine/ObjectCache.h +++ b/include/llvm/ExecutionEngine/ObjectCache.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H -#define LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H +#ifndef LLVM_EXECUTIONENGINE_OBJECTCACHE_H +#define LLVM_EXECUTIONENGINE_OBJECTCACHE_H #include "llvm/Support/MemoryBuffer.h" @@ -20,6 +20,7 @@ class Module; /// ExecutionEngine for the purpose of avoiding compilation for Modules that /// have already been compiled and an object file is available. class ObjectCache { + virtual void anchor(); public: ObjectCache() { } diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h index 9fddca7..076f4b1 100644 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ b/include/llvm/ExecutionEngine/ObjectImage.h @@ -25,6 +25,7 @@ namespace llvm { class ObjectImage { ObjectImage() LLVM_DELETED_FUNCTION; ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; + virtual void anchor(); protected: OwningPtr<ObjectBuffer> Buffer; diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index 99e2594..3ad2e50 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -21,6 +21,9 @@ namespace llvm { +class ExecutionEngine; +class ObjectImage; + // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of // JITMemoryManager required for dynamic loading of binaries. @@ -38,17 +41,30 @@ public: /// executable code. The SectionID is a unique identifier assigned by the JIT /// engine, and optionally recorded by the memory manager to access a loaded /// section. - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) = 0; + virtual uint8_t *allocateCodeSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName) = 0; /// Allocate a memory block of (at least) the given size suitable for data. /// The SectionID is a unique identifier assigned by the JIT engine, and /// optionally recorded by the memory manager to access a loaded section. - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, bool IsReadOnly) = 0; + virtual uint8_t *allocateDataSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool IsReadOnly) = 0; /// Register the EH frames with the runtime so that c++ exceptions work. - virtual void registerEHFrames(StringRef SectionData); + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + + virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + + /// This method returns the address of the specified function or variable. + /// It is used to resolve symbols during module linking. + virtual uint64_t getSymbolAddress(const std::string &Name); /// This method returns the address of the specified function. As such it is /// only useful for resolving library symbols, not code generated symbols. @@ -56,9 +72,25 @@ public: /// If \p AbortOnFailure is false and no function with the given name is /// found, this function returns a null pointer. Otherwise, it prints a /// message to stderr and aborts. + /// + /// This function is deprecated for memory managers to be used with + /// MCJIT or RuntimeDyld. Use getSymbolAddress instead. virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); + /// This method is called after an object has been loaded into memory but + /// before relocations are applied to the loaded sections. The object load + /// may have been initiated by MCJIT to resolve an external symbol for another + /// object that is being finalized. In that case, the object about which + /// the memory manager is being notified will be finalized immediately after + /// the memory manager returns from this call. + /// + /// Memory managers which are preparing code for execution in an external + /// address space can use this call to remap the section addresses for the + /// newly loaded object. + virtual void notifyObjectLoaded(ExecutionEngine *EE, + const ObjectImage *) {} + /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation /// to decide whether or not to act on this method. The memory manager will diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 1a57317..b832438 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -64,9 +64,16 @@ public: /// This is the address which will be used for relocation resolution. void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); - StringRef getErrorString(); + /// Register any EH frame sections that have been loaded but not previously + /// registered with the memory manager. Note, RuntimeDyld is responsible + /// for identifying the EH frame and calling the memory manager with the + /// EH frame section data. However, the memory manager itself will handle + /// the actual target-specific EH frame registration. + void registerEHFrames(); + + void deregisterEHFrames(); - StringRef getEHFrameSection(); + StringRef getErrorString(); }; } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index 6ee2a2a..fd6e41f 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -49,7 +49,8 @@ public: /// The value of \p Alignment must be a power of two. If \p Alignment is zero /// a default alignment of 16 will be used. virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, + StringRef SectionName); /// \brief Allocates a memory block of (at least) the given size suitable for /// executable code. @@ -58,6 +59,7 @@ public: /// a default alignment of 16 will be used. virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool isReadOnly); /// \brief Update section-specific memory permissions and other attributes. diff --git a/include/llvm/GVMaterializer.h b/include/llvm/GVMaterializer.h index 1e5c426..8efe50a 100644 --- a/include/llvm/GVMaterializer.h +++ b/include/llvm/GVMaterializer.h @@ -18,7 +18,7 @@ #ifndef LLVM_GVMATERIALIZER_H #define LLVM_GVMATERIALIZER_H -#include <string> +#include "llvm/Support/system_error.h" namespace llvm { @@ -41,11 +41,9 @@ public: /// dematerialized back to whatever backing store this GVMaterializer uses. virtual bool isDematerializable(const GlobalValue *GV) const = 0; - /// Materialize - make sure the given GlobalValue is fully read. If the - /// module is corrupt, this returns true and fills in the optional string with - /// information about the problem. If successful, this returns false. + /// Materialize - make sure the given GlobalValue is fully read. /// - virtual bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0) = 0; + virtual error_code Materialize(GlobalValue *GV) = 0; /// Dematerialize - If the given GlobalValue is read in, and if the /// GVMaterializer supports it, release the memory for the GV, and set it up @@ -55,10 +53,8 @@ public: virtual void Dematerialize(GlobalValue *) {} /// MaterializeModule - make sure the entire Module has been completely read. - /// On error, this returns true and fills in the optional string with - /// information about the problem. If successful, this returns false. /// - virtual bool MaterializeModule(Module *M, std::string *ErrInfo = 0) = 0; + virtual error_code MaterializeModule(Module *M) = 0; }; } // End llvm namespace diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 2183758..c23ba0f 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <bitset> #include <cassert> @@ -88,6 +89,7 @@ public: NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack OptimizeForSize, ///< opt_size + OptimizeNone, ///< Function must not be optimized. ReadNone, ///< Function does not access memory ReadOnly, ///< Function only reads from memory Returned, ///< Return value is always equal to this argument @@ -199,7 +201,7 @@ public: /// index `1'. class AttributeSet { public: - enum AttrIndex { + enum AttrIndex LLVM_ENUM_INT_TYPE(unsigned) { ReturnIndex = 0U, FunctionIndex = ~0U }; diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 585fc5e..4437af2 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -51,6 +51,13 @@ namespace CallingConv { // (HiPE). HiPE = 11, + // WebKit JS - Calling convention for stack based JavaScript calls + WebKit_JS = 12, + + // AnyReg - Calling convention for dynamic register based calls (e.g. + // stackmap and patchpoint intrinsics). + AnyReg = 13, + // Target - This is the start of the target-specific calling conventions, // e.g. fastcall and thiscall on X86. FirstTargetCC = 64, diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 99aed0d..dac20c9 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -862,6 +862,7 @@ public: static Constant *getPtrToInt(Constant *C, Type *Ty); static Constant *getIntToPtr(Constant *C, Type *Ty); static Constant *getBitCast (Constant *C, Type *Ty); + static Constant *getAddrSpaceCast(Constant *C, Type *Ty); static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } @@ -942,12 +943,20 @@ public: Type *Ty ///< The type to trunc or bitcast C to ); - /// @brief Create a BitCast or a PtrToInt cast constant expression + /// @brief Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant + /// expression. static Constant *getPointerCast( Constant *C, ///< The pointer value to be casted (operand 0) Type *Ty ///< The type to which cast should be made ); + /// @brief Create a BitCast or AddrSpaceCast for a pointer type depending on + /// the address space. + static Constant *getPointerBitCastOrAddrSpaceCast( + Constant *C, ///< The constant to addrspacecast or bitcast + Type *Ty ///< The type to bitcast or addrspacecast C to + ); + /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts static Constant *getIntegerCast( Constant *C, ///< The integer constant to be casted @@ -1079,8 +1088,8 @@ public: /// as this ConstantExpr. The instruction is not linked to any basic block. /// /// A better approach to this could be to have a constructor for Instruction - /// which would take a ConstantExpr parameter, but that would have spread - /// implementation details of ConstantExpr outside of Constants.cpp, which + /// which would take a ConstantExpr parameter, but that would have spread + /// implementation details of ConstantExpr outside of Constants.cpp, which /// would make it harder to remove ConstantExprs altogether. Instruction *getAsInstruction(); diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 269edeb..10630a2 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -369,6 +369,17 @@ public: /// least as big as Width bits. Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; + /// getLargestLegalIntType - Return the largest legal integer type, or null if + /// none are set. + Type *getLargestLegalIntType(LLVMContext &C) const { + unsigned LargestSize = getLargestLegalIntTypeSize(); + return (LargestSize == 0) ? 0 : Type::getIntNTy(C, LargestSize); + } + + /// getLargestLegalIntType - Return the size of largest legal integer type + /// size, or 0 if none are set. + unsigned getLargestLegalIntTypeSize() const; + /// getIndexedOffset - return the offset from the beginning of the type for /// the specified indices. This is used to implement getelementptr. uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const; @@ -451,7 +462,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { case Type::LabelTyID: return getPointerSizeInBits(0); case Type::PointerTyID: - return getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace()); + return getPointerSizeInBits(Ty->getPointerAddressSpace()); case Type::ArrayTyID: { ArrayType *ATy = cast<ArrayType>(Ty); return ATy->getNumElements() * @@ -461,7 +472,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { // Get the layout annotation... which is lazily created on demand. return getStructLayout(cast<StructType>(Ty))->getSizeInBits(); case Type::IntegerTyID: - return cast<IntegerType>(Ty)->getBitWidth(); + return Ty->getIntegerBitWidth(); case Type::HalfTyID: return 16; case Type::FloatTyID: diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 0e51c6f..bba7ecd 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -159,11 +159,11 @@ public: /// calling convention of this function. The enum values for the known /// calling conventions are defined in CallingConv.h. CallingConv::ID getCallingConv() const { - return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 1); + return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 2); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 1) | - (static_cast<unsigned>(CC) << 1)); + setValueSubclassData((getSubclassDataFromValue() & 3) | + (static_cast<unsigned>(CC) << 2)); } /// @brief Return the attribute list for this Function. @@ -427,6 +427,13 @@ public: size_t arg_size() const; bool arg_empty() const; + bool hasPrefixData() const { + return getSubclassDataFromValue() & 2; + } + + Constant *getPrefixData() const; + void setPrefixData(Constant *PrefixData); + /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the /// program, displaying the CFG of the current function with the code for each diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 883814a..fec61a7 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -66,14 +66,25 @@ public: } /// getAliasedGlobal() - Aliasee can be either global or bitcast of /// global. This method retrives the global for both aliasee flavours. - const GlobalValue *getAliasedGlobal() const; + GlobalValue *getAliasedGlobal(); + const GlobalValue *getAliasedGlobal() const { + return const_cast<GlobalAlias *>(this)->getAliasedGlobal(); + } /// resolveAliasedGlobal() - This method tries to ultimately resolve the alias /// by going through the aliasing chain and trying to find the very last /// global. Returns NULL if a cycle was found. If stopOnWeak is false, then /// the whole chain aliasing chain is traversed, otherwise - only strong /// aliases. - const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const; + GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true); + const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const { + return const_cast<GlobalAlias *>(this)->resolveAliasedGlobal(stopOnWeak); + } + + static bool isValidLinkage(LinkageTypes L) { + return isExternalLinkage(L) || isLocalLinkage(L) || + isWeakLinkage(L) || isLinkOnceLinkage(L); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 1dc99cf..4f20a31 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -35,7 +35,6 @@ public: AvailableExternallyLinkage, ///< Available for inspection, not emission. LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. - LinkOnceODRAutoHideLinkage, ///< Like LinkOnceODRLinkage but addr not taken. WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) WeakODRLinkage, ///< Same, but only replaced by something equivalent. AppendingLinkage, ///< Special purpose, only applies to global arrays @@ -123,12 +122,7 @@ public: return Linkage == AvailableExternallyLinkage; } static bool isLinkOnceLinkage(LinkageTypes Linkage) { - return Linkage == LinkOnceAnyLinkage || - Linkage == LinkOnceODRLinkage || - Linkage == LinkOnceODRAutoHideLinkage; - } - static bool isLinkOnceODRAutoHideLinkage(LinkageTypes Linkage) { - return Linkage == LinkOnceODRAutoHideLinkage; + return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; } static bool isWeakLinkage(LinkageTypes Linkage) { return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage; @@ -192,7 +186,6 @@ public: Linkage == WeakODRLinkage || Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || - Linkage == LinkOnceODRAutoHideLinkage || Linkage == CommonLinkage || Linkage == ExternalWeakLinkage || Linkage == LinkerPrivateWeakLinkage; @@ -205,9 +198,6 @@ public: bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(Linkage); } - bool hasLinkOnceODRAutoHideLinkage() const { - return isLinkOnceODRAutoHideLinkage(Linkage); - } bool hasWeakLinkage() const { return isWeakLinkage(Linkage); } diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index bfed507..660092d 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -84,9 +84,7 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// hasInitializer - Unless a global variable isExternal(), it has an - /// initializer. The initializer for the global variable/constant is held by - /// Initializer if an initializer is specified. + /// Definitions have initializers, declarations don't. /// inline bool hasInitializer() const { return !isDeclaration(); } diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index e396e71..8d1432d 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -25,6 +25,7 @@ #include "llvm/IR/Operator.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/ConstantFolder.h" +#include "llvm/Support/ValueHandle.h" namespace llvm { class MDNode; @@ -52,10 +53,13 @@ protected: BasicBlock *BB; BasicBlock::iterator InsertPt; LLVMContext &Context; + + MDNode *DefaultFPMathTag; + FastMathFlags FMF; public: - IRBuilderBase(LLVMContext &context) - : Context(context) { + IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = 0) + : Context(context), DefaultFPMathTag(FPMathTag), FMF() { ClearInsertionPoint(); } @@ -169,6 +173,68 @@ public: ClearInsertionPoint(); } + /// \brief Get the floating point math metadata being used. + MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } + + /// \brief Get the flags to be applied to created floating point ops + FastMathFlags getFastMathFlags() const { return FMF; } + + /// \brief Clear the fast-math flags. + void clearFastMathFlags() { FMF.clear(); } + + /// \brief Set the floating point math metadata to be used. + void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } + + /// \brief Set the fast-math flags to be used with generated fp-math operators + void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } + + //===--------------------------------------------------------------------===// + // RAII helpers. + //===--------------------------------------------------------------------===// + + // \brief RAII object that stores the current insertion point and restores it + // when the object is destroyed. This includes the debug location. + class InsertPointGuard { + IRBuilderBase &Builder; + AssertingVH<BasicBlock> Block; + BasicBlock::iterator Point; + DebugLoc DbgLoc; + + InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + + public: + InsertPointGuard(IRBuilderBase &B) + : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()), + DbgLoc(B.getCurrentDebugLocation()) {} + + ~InsertPointGuard() { + Builder.restoreIP(InsertPoint(Block, Point)); + Builder.SetCurrentDebugLocation(DbgLoc); + } + }; + + // \brief RAII object that stores the current fast math settings and restores + // them when the object is destroyed. + class FastMathFlagGuard { + IRBuilderBase &Builder; + FastMathFlags FMF; + MDNode *FPMathTag; + + FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + FastMathFlagGuard &operator=( + const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + + public: + FastMathFlagGuard(IRBuilderBase &B) + : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag) {} + + ~FastMathFlagGuard() { + Builder.FMF = FMF; + Builder.DefaultFPMathTag = FPMathTag; + } + }; + //===--------------------------------------------------------------------===// // Miscellaneous creation methods. //===--------------------------------------------------------------------===// @@ -354,76 +420,52 @@ template<bool preserveNames = true, typename T = ConstantFolder, typename Inserter = IRBuilderDefaultInserter<preserveNames> > class IRBuilder : public IRBuilderBase, public Inserter { T Folder; - MDNode *DefaultFPMathTag; - FastMathFlags FMF; public: IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(), MDNode *FPMathTag = 0) - : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(C, FPMathTag), Inserter(I), Folder(F) { } explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) - : IRBuilderBase(C), Folder(), DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(C, FPMathTag), Folder() { } explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB); } explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB); } explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0) - : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(IP->getContext(), FPMathTag), Folder() { SetInsertPoint(IP); SetCurrentDebugLocation(IP->getDebugLoc()); } explicit IRBuilder(Use &U, MDNode *FPMathTag = 0) - : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(U->getContext(), FPMathTag), Folder() { SetInsertPoint(U); SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc()); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB, IP); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB, IP); } /// \brief Get the constant folder being used. const T &getFolder() { return Folder; } - /// \brief Get the floating point math metadata being used. - MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } - - /// \brief Get the flags to be applied to created floating point ops - FastMathFlags getFastMathFlags() const { return FMF; } - - /// \brief Clear the fast-math flags. - void clearFastMathFlags() { FMF.clear(); } - - /// \brief SetDefaultFPMathTag - Set the floating point math metadata to be used. - void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } - - /// \brief Set the fast-math flags to be used with generated fp-math operators - void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } - /// \brief Return true if this builder is configured to actually add the /// requested names to IR created through it. bool isNamePreserving() const { return preserveNames; } @@ -1091,6 +1133,10 @@ public: const Twine &Name = "") { return CreateCast(Instruction::BitCast, V, DestTy, Name); } + Value *CreateAddrSpaceCast(Value *V, Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name); + } Value *CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 33e4ab8..3398a83 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -197,7 +197,7 @@ public: // These are helper methods for dealing with flags in the INLINEASM SDNode // in the backend. - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // Fixed operands on an INLINEASM SDNode. Op_InputChain = 0, Op_AsmString = 1, diff --git a/include/llvm/IR/Instruction.def b/include/llvm/IR/Instruction.def index e59a052..d46314c 100644 --- a/include/llvm/IR/Instruction.def +++ b/include/llvm/IR/Instruction.def @@ -154,25 +154,26 @@ HANDLE_CAST_INST(41, FPExt , FPExtInst ) // Extend floating point HANDLE_CAST_INST(42, PtrToInt, PtrToIntInst) // Pointer -> Integer HANDLE_CAST_INST(43, IntToPtr, IntToPtrInst) // Integer -> Pointer HANDLE_CAST_INST(44, BitCast , BitCastInst ) // Type cast - LAST_CAST_INST(44) +HANDLE_CAST_INST(45, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast + LAST_CAST_INST(45) // Other operators... - FIRST_OTHER_INST(45) -HANDLE_OTHER_INST(45, ICmp , ICmpInst ) // Integer comparison instruction -HANDLE_OTHER_INST(46, FCmp , FCmpInst ) // Floating point comparison instr. -HANDLE_OTHER_INST(47, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(48, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(49, Select , SelectInst ) // select instruction -HANDLE_OTHER_INST(50, UserOp1, Instruction) // May be used internally in a pass -HANDLE_OTHER_INST(51, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(52, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(53, ExtractElement, ExtractElementInst)// extract from vector -HANDLE_OTHER_INST(54, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(55, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(56, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(57, InsertValue, InsertValueInst) // insert into aggregate -HANDLE_OTHER_INST(58, LandingPad, LandingPadInst) // Landing pad instruction. - LAST_OTHER_INST(58) + FIRST_OTHER_INST(46) +HANDLE_OTHER_INST(46, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(47, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(48, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(49, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(57, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(58, InsertValue, InsertValueInst) // insert into aggregate +HANDLE_OTHER_INST(59, LandingPad, LandingPadInst) // Landing pad instruction. + LAST_OTHER_INST(59) #undef FIRST_TERM_INST #undef HANDLE_TERM_INST diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index e05c3a8..0843d8f 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -23,8 +23,6 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InstrTypes.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/IntegersSubset.h" -#include "llvm/Support/IntegersSubsetMapping.h" #include <iterator> namespace llvm { @@ -911,6 +909,18 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) /// must be identical types. /// \brief Represent an integer comparison operator. class ICmpInst: public CmpInst { + void AssertOK() { + assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE && + getPredicate() <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVectorTy() || + getOperand(0)->getType()->isPtrOrPtrVectorTy()) && + "Invalid operand types for ICmp instruction"); + } + protected: /// \brief Clone an identical ICmpInst virtual ICmpInst *clone_impl() const; @@ -925,15 +935,9 @@ public: ) : CmpInst(makeCmpResultType(LHS->getType()), Instruction::ICmp, pred, LHS, RHS, NameStr, InsertBefore) { - assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && - pred <= CmpInst::LAST_ICMP_PREDICATE && - "Invalid ICmp predicate value"); - assert(getOperand(0)->getType() == getOperand(1)->getType() && - "Both operands to ICmp instruction are not of the same type!"); - // Check that the operands are the right type - assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// \brief Constructor with insert-at-end semantics. @@ -946,15 +950,9 @@ public: ) : CmpInst(makeCmpResultType(LHS->getType()), Instruction::ICmp, pred, LHS, RHS, NameStr, &InsertAtEnd) { - assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && - pred <= CmpInst::LAST_ICMP_PREDICATE && - "Invalid ICmp predicate value"); - assert(getOperand(0)->getType() == getOperand(1)->getType() && - "Both operands to ICmp instruction are not of the same type!"); - // Check that the operands are the right type - assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// \brief Constructor with no-insertion semantics @@ -965,15 +963,9 @@ public: const Twine &NameStr = "" ///< Name of the instruction ) : CmpInst(makeCmpResultType(LHS->getType()), Instruction::ICmp, pred, LHS, RHS, NameStr) { - assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && - pred <= CmpInst::LAST_ICMP_PREDICATE && - "Invalid ICmp predicate value"); - assert(getOperand(0)->getType() == getOperand(1)->getType() && - "Both operands to ICmp instruction are not of the same type!"); - // Check that the operands are the right type - assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. @@ -2457,31 +2449,10 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) class SwitchInst : public TerminatorInst { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; unsigned ReservedSpace; - // Operands format: // Operand[0] = Value to switch on // Operand[1] = Default basic block destination // Operand[2n ] = Value to match // Operand[2n+1] = BasicBlock to go to on match - - // Store case values separately from operands list. We needn't User-Use - // concept here, since it is just a case value, it will always constant, - // and case value couldn't reused with another instructions/values. - // Additionally: - // It allows us to use custom type for case values that is not inherited - // from Value. Since case value is a complex type that implements - // the subset of integers, we needn't extract sub-constants within - // slow getAggregateElement method. - // For case values we will use std::list to by two reasons: - // 1. It allows to add/remove cases without whole collection reallocation. - // 2. In most of cases we needn't random access. - // Currently case values are also stored in Operands List, but it will moved - // out in future commits. - typedef std::list<IntegersSubset> Subsets; - typedef Subsets::iterator SubsetsIt; - typedef Subsets::const_iterator SubsetsConstIt; - - Subsets TheSubsets; - SwitchInst(const SwitchInst &SI); void init(Value *Value, BasicBlock *Default, unsigned NumReserved); void growOperands(); @@ -2506,25 +2477,121 @@ protected: virtual SwitchInst *clone_impl() const; public: - // FIXME: Currently there are a lot of unclean template parameters, - // we need to make refactoring in future. - // All these parameters are used to implement both iterator and const_iterator - // without code duplication. - // SwitchInstTy may be "const SwitchInst" or "SwitchInst" - // ConstantIntTy may be "const ConstantInt" or "ConstantInt" - // SubsetsItTy may be SubsetsConstIt or SubsetsIt - // BasicBlockTy may be "const BasicBlock" or "BasicBlock" - template <class SwitchInstTy, class ConstantIntTy, - class SubsetsItTy, class BasicBlockTy> - class CaseIteratorT; - - typedef CaseIteratorT<const SwitchInst, const ConstantInt, - SubsetsConstIt, const BasicBlock> ConstCaseIt; - class CaseIt; - // -2 static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1); + template <class SwitchInstTy, class ConstantIntTy, class BasicBlockTy> + class CaseIteratorT { + protected: + + SwitchInstTy *SI; + unsigned Index; + + public: + + typedef CaseIteratorT<SwitchInstTy, ConstantIntTy, BasicBlockTy> Self; + + /// Initializes case iterator for given SwitchInst and for given + /// case number. + CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) { + this->SI = SI; + Index = CaseNum; + } + + /// Initializes case iterator for given SwitchInst and for given + /// TerminatorInst's successor index. + static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) { + assert(SuccessorIndex < SI->getNumSuccessors() && + "Successor index # out of range!"); + return SuccessorIndex != 0 ? + Self(SI, SuccessorIndex - 1) : + Self(SI, DefaultPseudoIndex); + } + + /// Resolves case value for current case. + ConstantIntTy *getCaseValue() { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + return reinterpret_cast<ConstantIntTy*>(SI->getOperand(2 + Index*2)); + } + + /// Resolves successor for current case. + BasicBlockTy *getCaseSuccessor() { + assert((Index < SI->getNumCases() || + Index == DefaultPseudoIndex) && + "Index out the number of cases."); + return SI->getSuccessor(getSuccessorIndex()); + } + + /// Returns number of current case. + unsigned getCaseIndex() const { return Index; } + + /// Returns TerminatorInst's successor index for current case successor. + unsigned getSuccessorIndex() const { + assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) && + "Index out the number of cases."); + return Index != DefaultPseudoIndex ? Index + 1 : 0; + } + + Self operator++() { + // Check index correctness after increment. + // Note: Index == getNumCases() means end(). + assert(Index+1 <= SI->getNumCases() && "Index out the number of cases."); + ++Index; + return *this; + } + Self operator++(int) { + Self tmp = *this; + ++(*this); + return tmp; + } + Self operator--() { + // Check index correctness after decrement. + // Note: Index == getNumCases() means end(). + // Also allow "-1" iterator here. That will became valid after ++. + assert((Index == 0 || Index-1 <= SI->getNumCases()) && + "Index out the number of cases."); + --Index; + return *this; + } + Self operator--(int) { + Self tmp = *this; + --(*this); + return tmp; + } + bool operator==(const Self& RHS) const { + assert(RHS.SI == SI && "Incompatible operators."); + return RHS.Index == Index; + } + bool operator!=(const Self& RHS) const { + assert(RHS.SI == SI && "Incompatible operators."); + return RHS.Index != Index; + } + }; + + typedef CaseIteratorT<const SwitchInst, const ConstantInt, const BasicBlock> + ConstCaseIt; + + class CaseIt : public CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> { + + typedef CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> ParentTy; + + public: + + CaseIt(const ParentTy& Src) : ParentTy(Src) {} + CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {} + + /// Sets the new value for current case. + void setValue(ConstantInt *V) { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + SI->setOperand(2 + Index*2, reinterpret_cast<Value*>(V)); + } + + /// Sets the new successor for current case. + void setSuccessor(BasicBlock *S) { + SI->setSuccessor(getSuccessorIndex(), S); + } + }; + static SwitchInst *Create(Value *Value, BasicBlock *Default, unsigned NumCases, Instruction *InsertBefore = 0) { return new SwitchInst(Value, Default, NumCases, InsertBefore); @@ -2560,23 +2627,23 @@ public: /// Returns a read/write iterator that points to the first /// case in SwitchInst. CaseIt case_begin() { - return CaseIt(this, 0, TheSubsets.begin()); + return CaseIt(this, 0); } /// Returns a read-only iterator that points to the first /// case in the SwitchInst. ConstCaseIt case_begin() const { - return ConstCaseIt(this, 0, TheSubsets.begin()); + return ConstCaseIt(this, 0); } /// Returns a read/write iterator that points one past the last /// in the SwitchInst. CaseIt case_end() { - return CaseIt(this, getNumCases(), TheSubsets.end()); + return CaseIt(this, getNumCases()); } /// Returns a read-only iterator that points one past the last /// in the SwitchInst. ConstCaseIt case_end() const { - return ConstCaseIt(this, getNumCases(), TheSubsets.end()); + return ConstCaseIt(this, getNumCases()); } /// Returns an iterator that points to the default case. /// Note: this iterator allows to resolve successor only. Attempt @@ -2584,10 +2651,10 @@ public: /// Also note, that increment and decrement also causes an assertion and /// makes iterator invalid. CaseIt case_default() { - return CaseIt(this, DefaultPseudoIndex, TheSubsets.end()); + return CaseIt(this, DefaultPseudoIndex); } ConstCaseIt case_default() const { - return ConstCaseIt(this, DefaultPseudoIndex, TheSubsets.end()); + return ConstCaseIt(this, DefaultPseudoIndex); } /// findCaseValue - Search all of the case values for the specified constant. @@ -2596,13 +2663,13 @@ public: /// that it is handled by the default handler. CaseIt findCaseValue(const ConstantInt *C) { for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) - if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) + if (i.getCaseValue() == C) return i; return case_default(); } ConstCaseIt findCaseValue(const ConstantInt *C) const { for (ConstCaseIt i = case_begin(), e = case_end(); i != e; ++i) - if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) + if (i.getCaseValue() == C) return i; return case_default(); } @@ -2628,19 +2695,13 @@ public: /// point to the added case. void addCase(ConstantInt *OnVal, BasicBlock *Dest); - /// addCase - Add an entry to the switch instruction. - /// Note: - /// This action invalidates case_end(). Old case_end() iterator will - /// point to the added case. - void addCase(IntegersSubset& OnVal, BasicBlock *Dest); - /// removeCase - This method removes the specified case and its successor /// from the switch instruction. Note that this operation may reorder the /// remaining cases at index idx and above. /// Note: /// This action invalidates iterators for all cases following the one removed, /// including the case_end() iterator. - void removeCase(CaseIt& i); + void removeCase(CaseIt i); unsigned getNumSuccessors() const { return getNumOperands()/2; } BasicBlock *getSuccessor(unsigned idx) const { @@ -2652,190 +2713,7 @@ public: setOperand(idx*2+1, (Value*)NewSucc); } - uint16_t hash() const { - uint32_t NumberOfCases = (uint32_t)getNumCases(); - uint16_t Hash = (0xFFFF & NumberOfCases) ^ (NumberOfCases >> 16); - for (ConstCaseIt i = case_begin(), e = case_end(); - i != e; ++i) { - uint32_t NumItems = (uint32_t)i.getCaseValueEx().getNumItems(); - Hash = (Hash << 1) ^ (0xFFFF & NumItems) ^ (NumItems >> 16); - } - return Hash; - } - - // Case iterators definition. - - template <class SwitchInstTy, class ConstantIntTy, - class SubsetsItTy, class BasicBlockTy> - class CaseIteratorT { - protected: - - SwitchInstTy *SI; - unsigned Index; - SubsetsItTy SubsetIt; - - /// Initializes case iterator for given SwitchInst and for given - /// case number. - friend class SwitchInst; - CaseIteratorT(SwitchInstTy *SI, unsigned SuccessorIndex, - SubsetsItTy CaseValueIt) { - this->SI = SI; - Index = SuccessorIndex; - this->SubsetIt = CaseValueIt; - } - - public: - typedef typename SubsetsItTy::reference IntegersSubsetRef; - typedef CaseIteratorT<SwitchInstTy, ConstantIntTy, - SubsetsItTy, BasicBlockTy> Self; - - CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) { - this->SI = SI; - Index = CaseNum; - SubsetIt = SI->TheSubsets.begin(); - std::advance(SubsetIt, CaseNum); - } - - - /// Initializes case iterator for given SwitchInst and for given - /// TerminatorInst's successor index. - static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) { - assert(SuccessorIndex < SI->getNumSuccessors() && - "Successor index # out of range!"); - return SuccessorIndex != 0 ? - Self(SI, SuccessorIndex - 1) : - Self(SI, DefaultPseudoIndex); - } - - /// Resolves case value for current case. - ConstantIntTy *getCaseValue() { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - IntegersSubsetRef CaseRanges = *SubsetIt; - - // FIXME: Currently we work with ConstantInt based cases. - // So return CaseValue as ConstantInt. - return CaseRanges.getSingleNumber(0).toConstantInt(); - } - - /// Resolves case value for current case. - IntegersSubsetRef getCaseValueEx() { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - return *SubsetIt; - } - - /// Resolves successor for current case. - BasicBlockTy *getCaseSuccessor() { - assert((Index < SI->getNumCases() || - Index == DefaultPseudoIndex) && - "Index out the number of cases."); - return SI->getSuccessor(getSuccessorIndex()); - } - - /// Returns number of current case. - unsigned getCaseIndex() const { return Index; } - - /// Returns TerminatorInst's successor index for current case successor. - unsigned getSuccessorIndex() const { - assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) && - "Index out the number of cases."); - return Index != DefaultPseudoIndex ? Index + 1 : 0; - } - - Self operator++() { - // Check index correctness after increment. - // Note: Index == getNumCases() means end(). - assert(Index+1 <= SI->getNumCases() && "Index out the number of cases."); - ++Index; - if (Index == 0) - SubsetIt = SI->TheSubsets.begin(); - else - ++SubsetIt; - return *this; - } - Self operator++(int) { - Self tmp = *this; - ++(*this); - return tmp; - } - Self operator--() { - // Check index correctness after decrement. - // Note: Index == getNumCases() means end(). - // Also allow "-1" iterator here. That will became valid after ++. - unsigned NumCases = SI->getNumCases(); - assert((Index == 0 || Index-1 <= NumCases) && - "Index out the number of cases."); - --Index; - if (Index == NumCases) { - SubsetIt = SI->TheSubsets.end(); - return *this; - } - - if (Index != -1U) - --SubsetIt; - - return *this; - } - Self operator--(int) { - Self tmp = *this; - --(*this); - return tmp; - } - bool operator==(const Self& RHS) const { - assert(RHS.SI == SI && "Incompatible operators."); - return RHS.Index == Index; - } - bool operator!=(const Self& RHS) const { - assert(RHS.SI == SI && "Incompatible operators."); - return RHS.Index != Index; - } - }; - - class CaseIt : public CaseIteratorT<SwitchInst, ConstantInt, - SubsetsIt, BasicBlock> { - typedef CaseIteratorT<SwitchInst, ConstantInt, SubsetsIt, BasicBlock> - ParentTy; - - protected: - friend class SwitchInst; - CaseIt(SwitchInst *SI, unsigned CaseNum, SubsetsIt SubsetIt) : - ParentTy(SI, CaseNum, SubsetIt) {} - - void updateCaseValueOperand(IntegersSubset& V) { - SI->setOperand(2 + Index*2, reinterpret_cast<Value*>((Constant*)V)); - } - - public: - - CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {} - - CaseIt(const ParentTy& Src) : ParentTy(Src) {} - - /// Sets the new value for current case. - void setValue(ConstantInt *V) { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - IntegersSubsetToBB Mapping; - // FIXME: Currently we work with ConstantInt based cases. - // So inititalize IntItem container directly from ConstantInt. - Mapping.add(IntItem::fromConstantInt(V)); - *SubsetIt = Mapping.getCase(); - updateCaseValueOperand(*SubsetIt); - } - - /// Sets the new value for current case. - void setValueEx(IntegersSubset& V) { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - *SubsetIt = V; - updateCaseValueOperand(*SubsetIt); - } - - /// Sets the new successor for current case. - void setSuccessor(BasicBlock *S) { - SI->setSuccessor(getSuccessorIndex(), S); - } - }; - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Switch; } @@ -3034,7 +2912,7 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); - /// \brief Determine whether this call has the NoAlias attribute. + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); @@ -3737,6 +3615,43 @@ public: } }; +//===----------------------------------------------------------------------===// +// AddrSpaceCastInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a conversion between pointers from +/// one address space to another. +class AddrSpaceCastInst : public CastInst { +protected: + /// \brief Clone an identical AddrSpaceCastInst + virtual AddrSpaceCastInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + AddrSpaceCastInst( + Value *S, ///< The value to be casted + Type *Ty, ///< The type to casted to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + AddrSpaceCastInst( + Value *S, ///< The value to be casted + Type *Ty, ///< The type to casted to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == AddrSpaceCast; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index c81d110..473e525 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -77,7 +77,7 @@ namespace Intrinsic { /// getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { - Void, MMX, Metadata, Half, Float, Double, + Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, Argument, ExtendVecArgument, TruncVecArgument } Kind; diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 1a849c4..ded6cc1 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -140,6 +140,7 @@ def llvm_v8i1_ty : LLVMType<v8i1>; // 8 x i1 def llvm_v16i1_ty : LLVMType<v16i1>; // 16 x i1 def llvm_v32i1_ty : LLVMType<v32i1>; // 32 x i1 def llvm_v64i1_ty : LLVMType<v64i1>; // 64 x i1 +def llvm_v1i8_ty : LLVMType<v1i8>; // 1 x i8 def llvm_v2i8_ty : LLVMType<v2i8>; // 2 x i8 def llvm_v4i8_ty : LLVMType<v4i8>; // 4 x i8 def llvm_v8i8_ty : LLVMType<v8i8>; // 8 x i8 @@ -165,10 +166,15 @@ def llvm_v4i64_ty : LLVMType<v4i64>; // 4 x i64 def llvm_v8i64_ty : LLVMType<v8i64>; // 8 x i64 def llvm_v16i64_ty : LLVMType<v16i64>; // 16 x i64 +def llvm_v2f16_ty : LLVMType<v2f16>; // 2 x half (__fp16) +def llvm_v4f16_ty : LLVMType<v4f16>; // 4 x half (__fp16) +def llvm_v8f16_ty : LLVMType<v8f16>; // 8 x half (__fp16) +def llvm_v1f32_ty : LLVMType<v1f32>; // 1 x float def llvm_v2f32_ty : LLVMType<v2f32>; // 2 x float def llvm_v4f32_ty : LLVMType<v4f32>; // 4 x float def llvm_v8f32_ty : LLVMType<v8f32>; // 8 x float def llvm_v16f32_ty : LLVMType<v16f32>; // 16 x float +def llvm_v1f64_ty : LLVMType<v1f64>; // 1 x double def llvm_v2f64_ty : LLVMType<v2f64>; // 2 x double def llvm_v4f64_ty : LLVMType<v4f64>; // 4 x double def llvm_v8f64_ty : LLVMType<v8f64>; // 8 x double @@ -258,6 +264,8 @@ def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; // Stack Protector Intrinsic - The stackprotector intrinsic writes the stack // guard to the correct place on the stack frame. def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; +def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty], + [IntrReadWriteArgMem]>; //===------------------- Standard C Library Intrinsics --------------------===// // @@ -293,11 +301,14 @@ let Properties = [IntrReadMem] in { def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_copysign : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_ceil : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_trunc : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_rint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_nearbyint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_round : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; } let Properties = [IntrNoMem] in { @@ -317,7 +328,7 @@ def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>; def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; // Internal interface for object size checking -def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i1_ty], +def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty], [IntrNoMem]>, GCCBuiltin<"__builtin_object_size">; @@ -444,6 +455,19 @@ def int_invariant_end : Intrinsic<[], llvm_ptr_ty], [IntrReadWriteArgMem, NoCapture<2>]>; +//===------------------------ Stackmap Intrinsics -------------------------===// +// +def int_experimental_stackmap : Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty, llvm_vararg_ty]>; +def int_experimental_patchpoint_void : Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty]>; +def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], + [llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty]>; + //===-------------------------- Other Intrinsics --------------------------===// // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index d7b1947..68af8c1 100644 --- a/include/llvm/IR/IntrinsicsAArch64.td +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -17,12 +17,47 @@ let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". // Vector Absolute Compare (Floating Point) -def int_aarch64_neon_vacgeq : Intrinsic<[llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; -def int_aarch64_neon_vacgtq : Intrinsic<[llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; +def int_aarch64_neon_vacgeq : + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vacgtq : + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +// Vector saturating accumulate +def int_aarch64_neon_suqadd : Neon_2Arg_Intrinsic; +def int_aarch64_neon_usqadd : Neon_2Arg_Intrinsic; + +// Vector Bitwise reverse +def int_aarch64_neon_rbit : Neon_1Arg_Intrinsic; + +// Vector extract and narrow +def int_aarch64_neon_xtn : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +// Vector floating-point convert +def int_aarch64_neon_frintn : Neon_1Arg_Intrinsic; +def int_aarch64_neon_fsqrt : Neon_1Arg_Intrinsic; +def int_aarch64_neon_fcvtxn : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtns : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtnu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtps : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtpu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtms : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtmu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtas : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtau : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtzs : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtzu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; // Vector maxNum (Floating Point) def int_aarch64_neon_vmaxnm : Neon_2Arg_Intrinsic; @@ -36,6 +71,318 @@ def int_aarch64_neon_vpmaxnm : Neon_2Arg_Intrinsic; // Vector Pairwise minNum (Floating Point) def int_aarch64_neon_vpminnm : Neon_2Arg_Intrinsic; -// Vector Multiply Extended (Floating Point) -def int_aarch64_neon_vmulx : Neon_2Arg_Intrinsic; +// Vector Multiply Extended and Scalar Multiply Extended (Floating Point) +def int_aarch64_neon_vmulx : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; + +class Neon_N2V_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; +class Neon_N3V_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; +class Neon_N2V_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>, llvm_i32_ty], + [IntrNoMem]>; + +// Vector rounding shift right by immediate (Signed) +def int_aarch64_neon_vsrshr : Neon_N2V_Intrinsic; +def int_aarch64_neon_vurshr : Neon_N2V_Intrinsic; +def int_aarch64_neon_vsqshlu : Neon_N2V_Intrinsic; + +def int_aarch64_neon_vsri : Neon_N3V_Intrinsic; +def int_aarch64_neon_vsli : Neon_N3V_Intrinsic; + +def int_aarch64_neon_vsqshrun : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vrshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqrshrun : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vuqshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqrshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vuqrshrn : Neon_N2V_Narrow_Intrinsic; + +// Vector across +class Neon_Across_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +class Neon_2Arg_Across_Float_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_aarch64_neon_saddlv : Neon_Across_Intrinsic; +def int_aarch64_neon_uaddlv : Neon_Across_Intrinsic; +def int_aarch64_neon_smaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_umaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_sminv : Neon_Across_Intrinsic; +def int_aarch64_neon_uminv : Neon_Across_Intrinsic; +def int_aarch64_neon_vaddv : Neon_Across_Intrinsic; +def int_aarch64_neon_vmaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_vminv : Neon_Across_Intrinsic; +def int_aarch64_neon_vmaxnmv : Neon_Across_Intrinsic; +def int_aarch64_neon_vminnmv : Neon_Across_Intrinsic; + +// Vector Table Lookup. +def int_aarch64_neon_vtbl1 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbl2 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_aarch64_neon_vtbl3 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, + LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbl4 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; + +// Vector Table Extension. +// Some elements of the destination vector may not be updated, so the original +// value of that vector is passed as the first argument. The next 1-4 +// arguments after that are the table. +def int_aarch64_neon_vtbx1 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_aarch64_neon_vtbx2 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbx3 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbx4 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<1>, LLVMMatchType<0>], + [IntrNoMem]>; + +// Vector Load/store +def int_aarch64_neon_vld1x2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_aarch64_neon_vld1x3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_aarch64_neon_vld1x4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + +def int_aarch64_neon_vst1x2 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_aarch64_neon_vst1x3 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_aarch64_neon_vst1x4 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +// Scalar Add +def int_aarch64_neon_vaddds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vadddu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + + +// Scalar Sub +def int_aarch64_neon_vsubds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vsubdu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + + +// Scalar Shift +// Scalar Shift Left +def int_aarch64_neon_vshlds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vshldu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Saturating Shift Left +def int_aarch64_neon_vqshls : Neon_2Arg_Intrinsic; +def int_aarch64_neon_vqshlu : Neon_2Arg_Intrinsic; + +// Scalar Shift Rouding Left +def int_aarch64_neon_vrshlds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vrshldu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Saturating Rounding Shift Left +def int_aarch64_neon_vqrshls : Neon_2Arg_Intrinsic; +def int_aarch64_neon_vqrshlu : Neon_2Arg_Intrinsic; + +// Scalar Reduce Pairwise Add. +def int_aarch64_neon_vpadd : + Intrinsic<[llvm_v1i64_ty], [llvm_v2i64_ty],[IntrNoMem]>; +def int_aarch64_neon_vpfadd : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfaddq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Reduce Pairwise Floating Point Max/Min. +def int_aarch64_neon_vpmax : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpmaxq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vpmin : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpminq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Reduce Pairwise Floating Point Maxnm/Minnm. +def int_aarch64_neon_vpfmaxnm : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfmaxnmq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfminnm : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfminnmq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Signed Integer Convert To Floating-point +def int_aarch64_neon_vcvtf32_s32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_s64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Unsigned Integer Convert To Floating-point +def int_aarch64_neon_vcvtf32_u32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_u64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Floating-point Reciprocal Exponent +def int_aarch64_neon_vrecpx : Neon_1Arg_Intrinsic; + +class Neon_Cmp_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyvector_ty], + [IntrNoMem]>; + +// Scalar Compare Equal +def int_aarch64_neon_vceq : Neon_Cmp_Intrinsic; + +// Scalar Compare Greater-Than or Equal +def int_aarch64_neon_vcge : Neon_Cmp_Intrinsic; +def int_aarch64_neon_vchs : Neon_Cmp_Intrinsic; + +// Scalar Compare Less-Than or Equal +def int_aarch64_neon_vclez : Neon_Cmp_Intrinsic; + +// Scalar Compare Less-Than +def int_aarch64_neon_vcltz : Neon_Cmp_Intrinsic; + +// Scalar Compare Greater-Than +def int_aarch64_neon_vcgt : Neon_Cmp_Intrinsic; +def int_aarch64_neon_vchi : Neon_Cmp_Intrinsic; + +// Scalar Compare Bitwise Test Bits +def int_aarch64_neon_vtstd : Neon_Cmp_Intrinsic; + +// Scalar Floating-point Absolute Compare Greater Than Or Equal +def int_aarch64_neon_vcage : Neon_Cmp_Intrinsic; + +// Scalar Floating-point Absolute Compare Greater Than +def int_aarch64_neon_vcagt : Neon_Cmp_Intrinsic; + +// Scalar Signed Saturating Accumulated of Unsigned Value +def int_aarch64_neon_vuqadd : Neon_2Arg_Intrinsic; + +// Scalar Unsigned Saturating Accumulated of Signed Value +def int_aarch64_neon_vsqadd : Neon_2Arg_Intrinsic; + +// Scalar Absolute Value +def int_aarch64_neon_vabs : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Absolute Difference +def int_aarch64_neon_vabd : Neon_2Arg_Intrinsic; + +// Scalar Negate Value +def int_aarch64_neon_vneg : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Signed Saturating Doubling Multiply-Add Long +def int_aarch64_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; + +// Signed Saturating Doubling Multiply-Subtract Long +def int_aarch64_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; + +class Neon_2Arg_ShiftImm_Intrinsic + : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +class Neon_3Arg_ShiftImm_Intrinsic + : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +// Scalar Shift Right (Immediate) +def int_aarch64_neon_vshrds_n : Neon_2Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vshrdu_n : Neon_2Arg_ShiftImm_Intrinsic; + +// Scalar Shift Right and Accumulate (Immediate) +def int_aarch64_neon_vsrads_n : Neon_3Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vsradu_n : Neon_3Arg_ShiftImm_Intrinsic; + +// Scalar Rounding Shift Right and Accumulate (Immediate) +def int_aarch64_neon_vrsrads_n : Neon_3Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vrsradu_n : Neon_3Arg_ShiftImm_Intrinsic; + +// Scalar Shift Left (Immediate) +def int_aarch64_neon_vshld_n : Neon_2Arg_ShiftImm_Intrinsic; + +// Scalar Saturating Shift Left (Immediate) +def int_aarch64_neon_vqshls_n : Neon_N2V_Intrinsic; +def int_aarch64_neon_vqshlu_n : Neon_N2V_Intrinsic; + +// Scalar Signed Saturating Shift Left Unsigned (Immediate) +def int_aarch64_neon_vqshlus_n : Neon_N2V_Intrinsic; + +// Scalar Signed Fixed-point Convert To Floating-Point (Immediate) +def int_aarch64_neon_vcvtf32_n_s32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_n_s64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Unsigned Fixed-point Convert To Floating-Point (Immediate) +def int_aarch64_neon_vcvtf32_n_u32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_n_u64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Floating-point Convert To Signed Fixed-point (Immediate) +def int_aarch64_neon_vcvts_n_s32_f32 : + Intrinsic<[llvm_v1i32_ty], [llvm_v1f32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtd_n_s64_f64 : + Intrinsic<[llvm_v1i64_ty], [llvm_v1f64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Floating-point Convert To Unsigned Fixed-point (Immediate) +def int_aarch64_neon_vcvts_n_u32_f32 : + Intrinsic<[llvm_v1i32_ty], [llvm_v1f32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtd_n_u64_f64 : + Intrinsic<[llvm_v1i64_ty], [llvm_v1f64_ty, llvm_i32_ty], [IntrNoMem]>; + +class Neon_SHA_Intrinsic + : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v1i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_aarch64_neon_sha1c : Neon_SHA_Intrinsic; +def int_aarch64_neon_sha1m : Neon_SHA_Intrinsic; +def int_aarch64_neon_sha1p : Neon_SHA_Intrinsic; } diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index 3c5d5ff..0b50d64 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -45,6 +45,11 @@ def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; //===----------------------------------------------------------------------===// +// Data barrier instructions +def int_arm_dmb : GCCBuiltin<"__builtin_arm_dmb">, Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dsb : GCCBuiltin<"__builtin_arm_dsb">, Intrinsic<[], [llvm_i32_ty]>; + +//===----------------------------------------------------------------------===// // VFP def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">, @@ -92,6 +97,26 @@ def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">, llvm_i32_ty, llvm_i32_ty], []>; //===----------------------------------------------------------------------===// +// CRC32 + +def int_arm_crc32b : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32cb : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32h : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32ch : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32w : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// HINT +def int_arm_sevl : Intrinsic<[], []>; + +//===----------------------------------------------------------------------===// // Advanced SIMD (NEON) // The following classes do not correspond directly to GCC builtins. @@ -163,7 +188,6 @@ let Properties = [IntrNoMem, Commutative] in { def int_arm_neon_vrhaddu : Neon_2Arg_Intrinsic; def int_arm_neon_vqadds : Neon_2Arg_Intrinsic; def int_arm_neon_vqaddu : Neon_2Arg_Intrinsic; - def int_arm_neon_vaddhn : Neon_2Arg_Narrow_Intrinsic; def int_arm_neon_vraddhn : Neon_2Arg_Narrow_Intrinsic; // Vector Multiply. @@ -175,10 +199,6 @@ let Properties = [IntrNoMem, Commutative] in { def int_arm_neon_vmullp : Neon_2Arg_Long_Intrinsic; def int_arm_neon_vqdmull : Neon_2Arg_Long_Intrinsic; - // Vector Multiply and Accumulate/Subtract. - def int_arm_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; - def int_arm_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; - // Vector Maximum. def int_arm_neon_vmaxs : Neon_2Arg_Intrinsic; def int_arm_neon_vmaxu : Neon_2Arg_Intrinsic; @@ -201,7 +221,6 @@ def int_arm_neon_vhsubs : Neon_2Arg_Intrinsic; def int_arm_neon_vhsubu : Neon_2Arg_Intrinsic; def int_arm_neon_vqsubs : Neon_2Arg_Intrinsic; def int_arm_neon_vqsubu : Neon_2Arg_Intrinsic; -def int_arm_neon_vsubhn : Neon_2Arg_Narrow_Intrinsic; def int_arm_neon_vrsubhn : Neon_2Arg_Narrow_Intrinsic; // Vector Absolute Compare. @@ -451,4 +470,21 @@ def int_arm_neon_vbsl : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; + +// Crypto instructions +def int_arm_neon_aesd : Neon_2Arg_Intrinsic; +def int_arm_neon_aese : Neon_2Arg_Intrinsic; +def int_arm_neon_aesimc : Neon_1Arg_Intrinsic; +def int_arm_neon_aesmc : Neon_1Arg_Intrinsic; +def int_arm_neon_sha1h : Neon_1Arg_Intrinsic; +def int_arm_neon_sha1su1 : Neon_2Arg_Intrinsic; +def int_arm_neon_sha256su0 : Neon_2Arg_Intrinsic; +def int_arm_neon_sha1c : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1m : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1p : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1su0: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256h: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256h2: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256su1: Neon_3Arg_Intrinsic; + } // end TargetPrefix diff --git a/include/llvm/IR/IntrinsicsMips.td b/include/llvm/IR/IntrinsicsMips.td index a0987c8..42c5821 100644 --- a/include/llvm/IR/IntrinsicsMips.td +++ b/include/llvm/IR/IntrinsicsMips.td @@ -386,4 +386,1372 @@ def int_mips_subuh_qb: GCCBuiltin<"__builtin_mips_subuh_qb">, Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; def int_mips_subuh_r_qb: GCCBuiltin<"__builtin_mips_subuh_r_qb">, Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// MIPS MSA + +//===----------------------------------------------------------------------===// +// Addition/subtraction + +def int_mips_add_a_b : GCCBuiltin<"__builtin_msa_add_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_h : GCCBuiltin<"__builtin_msa_add_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_w : GCCBuiltin<"__builtin_msa_add_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_d : GCCBuiltin<"__builtin_msa_add_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_a_b : GCCBuiltin<"__builtin_msa_adds_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_h : GCCBuiltin<"__builtin_msa_adds_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_w : GCCBuiltin<"__builtin_msa_adds_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_d : GCCBuiltin<"__builtin_msa_adds_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_s_b : GCCBuiltin<"__builtin_msa_adds_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_h : GCCBuiltin<"__builtin_msa_adds_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_w : GCCBuiltin<"__builtin_msa_adds_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_d : GCCBuiltin<"__builtin_msa_adds_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_u_b : GCCBuiltin<"__builtin_msa_adds_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_h : GCCBuiltin<"__builtin_msa_adds_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_w : GCCBuiltin<"__builtin_msa_adds_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_d : GCCBuiltin<"__builtin_msa_adds_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_addv_b : GCCBuiltin<"__builtin_msa_addv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_h : GCCBuiltin<"__builtin_msa_addv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_w : GCCBuiltin<"__builtin_msa_addv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_d : GCCBuiltin<"__builtin_msa_addv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_addvi_b : GCCBuiltin<"__builtin_msa_addvi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_h : GCCBuiltin<"__builtin_msa_addvi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_w : GCCBuiltin<"__builtin_msa_addvi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_d : GCCBuiltin<"__builtin_msa_addvi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; + +def int_mips_and_v : GCCBuiltin<"__builtin_msa_and_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_andi_b : GCCBuiltin<"__builtin_msa_andi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_asub_s_b : GCCBuiltin<"__builtin_msa_asub_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_asub_s_h : GCCBuiltin<"__builtin_msa_asub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_asub_s_w : GCCBuiltin<"__builtin_msa_asub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_asub_s_d : GCCBuiltin<"__builtin_msa_asub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_asub_u_b : GCCBuiltin<"__builtin_msa_asub_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_asub_u_h : GCCBuiltin<"__builtin_msa_asub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_asub_u_w : GCCBuiltin<"__builtin_msa_asub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_asub_u_d : GCCBuiltin<"__builtin_msa_asub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ave_s_b : GCCBuiltin<"__builtin_msa_ave_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_h : GCCBuiltin<"__builtin_msa_ave_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_w : GCCBuiltin<"__builtin_msa_ave_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_d : GCCBuiltin<"__builtin_msa_ave_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_ave_u_b : GCCBuiltin<"__builtin_msa_ave_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_h : GCCBuiltin<"__builtin_msa_ave_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_w : GCCBuiltin<"__builtin_msa_ave_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_d : GCCBuiltin<"__builtin_msa_ave_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_aver_s_b : GCCBuiltin<"__builtin_msa_aver_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_h : GCCBuiltin<"__builtin_msa_aver_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_w : GCCBuiltin<"__builtin_msa_aver_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_d : GCCBuiltin<"__builtin_msa_aver_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_aver_u_b : GCCBuiltin<"__builtin_msa_aver_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_h : GCCBuiltin<"__builtin_msa_aver_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_w : GCCBuiltin<"__builtin_msa_aver_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_d : GCCBuiltin<"__builtin_msa_aver_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_bclr_b : GCCBuiltin<"__builtin_msa_bclr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bclr_h : GCCBuiltin<"__builtin_msa_bclr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bclr_w : GCCBuiltin<"__builtin_msa_bclr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bclr_d : GCCBuiltin<"__builtin_msa_bclr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bclri_b : GCCBuiltin<"__builtin_msa_bclri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_h : GCCBuiltin<"__builtin_msa_bclri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_w : GCCBuiltin<"__builtin_msa_bclri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_d : GCCBuiltin<"__builtin_msa_bclri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_binsl_b : GCCBuiltin<"__builtin_msa_binsl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_binsl_h : GCCBuiltin<"__builtin_msa_binsl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_binsl_w : GCCBuiltin<"__builtin_msa_binsl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_binsl_d : GCCBuiltin<"__builtin_msa_binsl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_binsli_b : GCCBuiltin<"__builtin_msa_binsli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_h : GCCBuiltin<"__builtin_msa_binsli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_w : GCCBuiltin<"__builtin_msa_binsli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_d : GCCBuiltin<"__builtin_msa_binsli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_binsr_b : GCCBuiltin<"__builtin_msa_binsr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_binsr_h : GCCBuiltin<"__builtin_msa_binsr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_binsr_w : GCCBuiltin<"__builtin_msa_binsr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_binsr_d : GCCBuiltin<"__builtin_msa_binsr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_binsri_b : GCCBuiltin<"__builtin_msa_binsri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_h : GCCBuiltin<"__builtin_msa_binsri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_w : GCCBuiltin<"__builtin_msa_binsri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_d : GCCBuiltin<"__builtin_msa_binsri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bmnz_v : GCCBuiltin<"__builtin_msa_bmnz_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bmnzi_b : GCCBuiltin<"__builtin_msa_bmnzi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bmz_v : GCCBuiltin<"__builtin_msa_bmz_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bmzi_b : GCCBuiltin<"__builtin_msa_bmzi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bneg_b : GCCBuiltin<"__builtin_msa_bneg_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bneg_h : GCCBuiltin<"__builtin_msa_bneg_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bneg_w : GCCBuiltin<"__builtin_msa_bneg_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bneg_d : GCCBuiltin<"__builtin_msa_bneg_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bnegi_b : GCCBuiltin<"__builtin_msa_bnegi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_h : GCCBuiltin<"__builtin_msa_bnegi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_w : GCCBuiltin<"__builtin_msa_bnegi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_d : GCCBuiltin<"__builtin_msa_bnegi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_bnz_b : GCCBuiltin<"__builtin_msa_bnz_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bnz_h : GCCBuiltin<"__builtin_msa_bnz_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bnz_w : GCCBuiltin<"__builtin_msa_bnz_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bnz_d : GCCBuiltin<"__builtin_msa_bnz_d">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bnz_v : GCCBuiltin<"__builtin_msa_bnz_v">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_bsel_v : GCCBuiltin<"__builtin_msa_bsel_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bseli_b : GCCBuiltin<"__builtin_msa_bseli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bset_b : GCCBuiltin<"__builtin_msa_bset_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bset_h : GCCBuiltin<"__builtin_msa_bset_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bset_w : GCCBuiltin<"__builtin_msa_bset_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bset_d : GCCBuiltin<"__builtin_msa_bset_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bseti_b : GCCBuiltin<"__builtin_msa_bseti_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_h : GCCBuiltin<"__builtin_msa_bseti_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_w : GCCBuiltin<"__builtin_msa_bseti_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_d : GCCBuiltin<"__builtin_msa_bseti_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_bz_b : GCCBuiltin<"__builtin_msa_bz_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bz_h : GCCBuiltin<"__builtin_msa_bz_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bz_w : GCCBuiltin<"__builtin_msa_bz_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bz_d : GCCBuiltin<"__builtin_msa_bz_d">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bz_v : GCCBuiltin<"__builtin_msa_bz_v">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_ceq_b : GCCBuiltin<"__builtin_msa_ceq_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ceq_h : GCCBuiltin<"__builtin_msa_ceq_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ceq_w : GCCBuiltin<"__builtin_msa_ceq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ceq_d : GCCBuiltin<"__builtin_msa_ceq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ceqi_b : GCCBuiltin<"__builtin_msa_ceqi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_h : GCCBuiltin<"__builtin_msa_ceqi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_w : GCCBuiltin<"__builtin_msa_ceqi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_d : GCCBuiltin<"__builtin_msa_ceqi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_cfcmsa : GCCBuiltin<"__builtin_msa_cfcmsa">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + +def int_mips_cle_s_b : GCCBuiltin<"__builtin_msa_cle_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_cle_s_h : GCCBuiltin<"__builtin_msa_cle_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_cle_s_w : GCCBuiltin<"__builtin_msa_cle_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_cle_s_d : GCCBuiltin<"__builtin_msa_cle_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_cle_u_b : GCCBuiltin<"__builtin_msa_cle_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_cle_u_h : GCCBuiltin<"__builtin_msa_cle_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_cle_u_w : GCCBuiltin<"__builtin_msa_cle_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_cle_u_d : GCCBuiltin<"__builtin_msa_cle_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clei_s_b : GCCBuiltin<"__builtin_msa_clei_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_h : GCCBuiltin<"__builtin_msa_clei_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_w : GCCBuiltin<"__builtin_msa_clei_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_d : GCCBuiltin<"__builtin_msa_clei_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clei_u_b : GCCBuiltin<"__builtin_msa_clei_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_h : GCCBuiltin<"__builtin_msa_clei_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_w : GCCBuiltin<"__builtin_msa_clei_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_d : GCCBuiltin<"__builtin_msa_clei_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clt_s_b : GCCBuiltin<"__builtin_msa_clt_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_clt_s_h : GCCBuiltin<"__builtin_msa_clt_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_clt_s_w : GCCBuiltin<"__builtin_msa_clt_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_clt_s_d : GCCBuiltin<"__builtin_msa_clt_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clt_u_b : GCCBuiltin<"__builtin_msa_clt_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_clt_u_h : GCCBuiltin<"__builtin_msa_clt_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_clt_u_w : GCCBuiltin<"__builtin_msa_clt_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_clt_u_d : GCCBuiltin<"__builtin_msa_clt_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clti_s_b : GCCBuiltin<"__builtin_msa_clti_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_h : GCCBuiltin<"__builtin_msa_clti_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_w : GCCBuiltin<"__builtin_msa_clti_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_d : GCCBuiltin<"__builtin_msa_clti_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clti_u_b : GCCBuiltin<"__builtin_msa_clti_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_h : GCCBuiltin<"__builtin_msa_clti_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_w : GCCBuiltin<"__builtin_msa_clti_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_d : GCCBuiltin<"__builtin_msa_clti_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_copy_s_b : GCCBuiltin<"__builtin_msa_copy_s_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_h : GCCBuiltin<"__builtin_msa_copy_s_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_w : GCCBuiltin<"__builtin_msa_copy_s_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_d : GCCBuiltin<"__builtin_msa_copy_s_d">, + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_copy_u_b : GCCBuiltin<"__builtin_msa_copy_u_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_h : GCCBuiltin<"__builtin_msa_copy_u_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_w : GCCBuiltin<"__builtin_msa_copy_u_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_d : GCCBuiltin<"__builtin_msa_copy_u_d">, + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_ctcmsa : GCCBuiltin<"__builtin_msa_ctcmsa">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; + +def int_mips_div_s_b : GCCBuiltin<"__builtin_msa_div_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_div_s_h : GCCBuiltin<"__builtin_msa_div_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_div_s_w : GCCBuiltin<"__builtin_msa_div_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_div_s_d : GCCBuiltin<"__builtin_msa_div_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_div_u_b : GCCBuiltin<"__builtin_msa_div_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_div_u_h : GCCBuiltin<"__builtin_msa_div_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_div_u_w : GCCBuiltin<"__builtin_msa_div_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_div_u_d : GCCBuiltin<"__builtin_msa_div_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_dotp_s_h : GCCBuiltin<"__builtin_msa_dotp_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_dotp_s_w : GCCBuiltin<"__builtin_msa_dotp_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_dotp_s_d : GCCBuiltin<"__builtin_msa_dotp_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_dotp_u_h : GCCBuiltin<"__builtin_msa_dotp_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_dotp_u_w : GCCBuiltin<"__builtin_msa_dotp_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_dotp_u_d : GCCBuiltin<"__builtin_msa_dotp_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_dpadd_s_h : GCCBuiltin<"__builtin_msa_dpadd_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpadd_s_w : GCCBuiltin<"__builtin_msa_dpadd_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpadd_s_d : GCCBuiltin<"__builtin_msa_dpadd_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpadd_u_h : GCCBuiltin<"__builtin_msa_dpadd_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpadd_u_w : GCCBuiltin<"__builtin_msa_dpadd_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpadd_u_d : GCCBuiltin<"__builtin_msa_dpadd_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpsub_s_h : GCCBuiltin<"__builtin_msa_dpsub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpsub_s_w : GCCBuiltin<"__builtin_msa_dpsub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpsub_s_d : GCCBuiltin<"__builtin_msa_dpsub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpsub_u_h : GCCBuiltin<"__builtin_msa_dpsub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpsub_u_w : GCCBuiltin<"__builtin_msa_dpsub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpsub_u_d : GCCBuiltin<"__builtin_msa_dpsub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_fadd_w : GCCBuiltin<"__builtin_msa_fadd_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fadd_d : GCCBuiltin<"__builtin_msa_fadd_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcaf_w : GCCBuiltin<"__builtin_msa_fcaf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcaf_d : GCCBuiltin<"__builtin_msa_fcaf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fceq_w : GCCBuiltin<"__builtin_msa_fceq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fceq_d : GCCBuiltin<"__builtin_msa_fceq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcle_w : GCCBuiltin<"__builtin_msa_fcle_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcle_d : GCCBuiltin<"__builtin_msa_fcle_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fclt_w : GCCBuiltin<"__builtin_msa_fclt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fclt_d : GCCBuiltin<"__builtin_msa_fclt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fclass_w : GCCBuiltin<"__builtin_msa_fclass_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fclass_d : GCCBuiltin<"__builtin_msa_fclass_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcne_w : GCCBuiltin<"__builtin_msa_fcne_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcne_d : GCCBuiltin<"__builtin_msa_fcne_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcor_w : GCCBuiltin<"__builtin_msa_fcor_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcor_d : GCCBuiltin<"__builtin_msa_fcor_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcueq_w : GCCBuiltin<"__builtin_msa_fcueq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcueq_d : GCCBuiltin<"__builtin_msa_fcueq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcule_w : GCCBuiltin<"__builtin_msa_fcule_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcule_d : GCCBuiltin<"__builtin_msa_fcule_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcult_w : GCCBuiltin<"__builtin_msa_fcult_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcult_d : GCCBuiltin<"__builtin_msa_fcult_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcun_w : GCCBuiltin<"__builtin_msa_fcun_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcun_d : GCCBuiltin<"__builtin_msa_fcun_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcune_w : GCCBuiltin<"__builtin_msa_fcune_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcune_d : GCCBuiltin<"__builtin_msa_fcune_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fdiv_w : GCCBuiltin<"__builtin_msa_fdiv_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fdiv_d : GCCBuiltin<"__builtin_msa_fdiv_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fexdo_h : GCCBuiltin<"__builtin_msa_fexdo_h">, + Intrinsic<[llvm_v8f16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fexdo_w : GCCBuiltin<"__builtin_msa_fexdo_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fexp2_w : GCCBuiltin<"__builtin_msa_fexp2_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_fexp2_d : GCCBuiltin<"__builtin_msa_fexp2_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_fexupl_w : GCCBuiltin<"__builtin_msa_fexupl_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8f16_ty], [IntrNoMem]>; +def int_mips_fexupl_d : GCCBuiltin<"__builtin_msa_fexupl_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_mips_fexupr_w : GCCBuiltin<"__builtin_msa_fexupr_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8f16_ty], [IntrNoMem]>; +def int_mips_fexupr_d : GCCBuiltin<"__builtin_msa_fexupr_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_mips_ffint_s_w : GCCBuiltin<"__builtin_msa_ffint_s_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ffint_s_d : GCCBuiltin<"__builtin_msa_ffint_s_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ffint_u_w : GCCBuiltin<"__builtin_msa_ffint_u_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ffint_u_d : GCCBuiltin<"__builtin_msa_ffint_u_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ffql_w : GCCBuiltin<"__builtin_msa_ffql_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ffql_d : GCCBuiltin<"__builtin_msa_ffql_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_ffqr_w : GCCBuiltin<"__builtin_msa_ffqr_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ffqr_d : GCCBuiltin<"__builtin_msa_ffqr_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_fill_b : GCCBuiltin<"__builtin_msa_fill_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_h : GCCBuiltin<"__builtin_msa_fill_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_w : GCCBuiltin<"__builtin_msa_fill_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_d : GCCBuiltin<"__builtin_msa_fill_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_i64_ty], [IntrNoMem]>; + +def int_mips_flog2_w : GCCBuiltin<"__builtin_msa_flog2_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_flog2_d : GCCBuiltin<"__builtin_msa_flog2_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmadd_w : GCCBuiltin<"__builtin_msa_fmadd_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +def int_mips_fmadd_d : GCCBuiltin<"__builtin_msa_fmadd_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +def int_mips_fmax_w : GCCBuiltin<"__builtin_msa_fmax_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmax_d : GCCBuiltin<"__builtin_msa_fmax_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmax_a_w : GCCBuiltin<"__builtin_msa_fmax_a_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmax_a_d : GCCBuiltin<"__builtin_msa_fmax_a_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmin_w : GCCBuiltin<"__builtin_msa_fmin_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmin_d : GCCBuiltin<"__builtin_msa_fmin_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmin_a_w : GCCBuiltin<"__builtin_msa_fmin_a_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmin_a_d : GCCBuiltin<"__builtin_msa_fmin_a_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmsub_w : GCCBuiltin<"__builtin_msa_fmsub_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +def int_mips_fmsub_d : GCCBuiltin<"__builtin_msa_fmsub_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +def int_mips_fmul_w : GCCBuiltin<"__builtin_msa_fmul_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmul_d : GCCBuiltin<"__builtin_msa_fmul_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frint_w : GCCBuiltin<"__builtin_msa_frint_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frint_d : GCCBuiltin<"__builtin_msa_frint_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frcp_w : GCCBuiltin<"__builtin_msa_frcp_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frcp_d : GCCBuiltin<"__builtin_msa_frcp_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frsqrt_w : GCCBuiltin<"__builtin_msa_frsqrt_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frsqrt_d : GCCBuiltin<"__builtin_msa_frsqrt_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsaf_w : GCCBuiltin<"__builtin_msa_fsaf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsaf_d : GCCBuiltin<"__builtin_msa_fsaf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fseq_w : GCCBuiltin<"__builtin_msa_fseq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fseq_d : GCCBuiltin<"__builtin_msa_fseq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsle_w : GCCBuiltin<"__builtin_msa_fsle_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsle_d : GCCBuiltin<"__builtin_msa_fsle_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fslt_w : GCCBuiltin<"__builtin_msa_fslt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fslt_d : GCCBuiltin<"__builtin_msa_fslt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsne_w : GCCBuiltin<"__builtin_msa_fsne_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsne_d : GCCBuiltin<"__builtin_msa_fsne_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsor_w : GCCBuiltin<"__builtin_msa_fsor_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsor_d : GCCBuiltin<"__builtin_msa_fsor_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsqrt_w : GCCBuiltin<"__builtin_msa_fsqrt_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsqrt_d : GCCBuiltin<"__builtin_msa_fsqrt_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsub_w : GCCBuiltin<"__builtin_msa_fsub_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsub_d : GCCBuiltin<"__builtin_msa_fsub_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsueq_w : GCCBuiltin<"__builtin_msa_fsueq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsueq_d : GCCBuiltin<"__builtin_msa_fsueq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsule_w : GCCBuiltin<"__builtin_msa_fsule_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsule_d : GCCBuiltin<"__builtin_msa_fsule_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsult_w : GCCBuiltin<"__builtin_msa_fsult_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsult_d : GCCBuiltin<"__builtin_msa_fsult_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsun_w : GCCBuiltin<"__builtin_msa_fsun_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsun_d : GCCBuiltin<"__builtin_msa_fsun_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsune_w : GCCBuiltin<"__builtin_msa_fsune_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsune_d : GCCBuiltin<"__builtin_msa_fsune_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftint_s_w : GCCBuiltin<"__builtin_msa_ftint_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftint_s_d : GCCBuiltin<"__builtin_msa_ftint_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftint_u_w : GCCBuiltin<"__builtin_msa_ftint_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftint_u_d : GCCBuiltin<"__builtin_msa_ftint_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftq_h : GCCBuiltin<"__builtin_msa_ftq_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftq_w : GCCBuiltin<"__builtin_msa_ftq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftrunc_s_w : GCCBuiltin<"__builtin_msa_ftrunc_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftrunc_s_d : GCCBuiltin<"__builtin_msa_ftrunc_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftrunc_u_w : GCCBuiltin<"__builtin_msa_ftrunc_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftrunc_u_d : GCCBuiltin<"__builtin_msa_ftrunc_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_hadd_s_h : GCCBuiltin<"__builtin_msa_hadd_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hadd_s_w : GCCBuiltin<"__builtin_msa_hadd_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hadd_s_d : GCCBuiltin<"__builtin_msa_hadd_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hadd_u_h : GCCBuiltin<"__builtin_msa_hadd_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hadd_u_w : GCCBuiltin<"__builtin_msa_hadd_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hadd_u_d : GCCBuiltin<"__builtin_msa_hadd_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hsub_s_h : GCCBuiltin<"__builtin_msa_hsub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hsub_s_w : GCCBuiltin<"__builtin_msa_hsub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hsub_s_d : GCCBuiltin<"__builtin_msa_hsub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hsub_u_h : GCCBuiltin<"__builtin_msa_hsub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hsub_u_w : GCCBuiltin<"__builtin_msa_hsub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hsub_u_d : GCCBuiltin<"__builtin_msa_hsub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_ilvev_b : GCCBuiltin<"__builtin_msa_ilvev_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvev_h : GCCBuiltin<"__builtin_msa_ilvev_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvev_w : GCCBuiltin<"__builtin_msa_ilvev_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvev_d : GCCBuiltin<"__builtin_msa_ilvev_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvl_b : GCCBuiltin<"__builtin_msa_ilvl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvl_h : GCCBuiltin<"__builtin_msa_ilvl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvl_w : GCCBuiltin<"__builtin_msa_ilvl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvl_d : GCCBuiltin<"__builtin_msa_ilvl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvod_b : GCCBuiltin<"__builtin_msa_ilvod_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvod_h : GCCBuiltin<"__builtin_msa_ilvod_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvod_w : GCCBuiltin<"__builtin_msa_ilvod_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvod_d : GCCBuiltin<"__builtin_msa_ilvod_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvr_b : GCCBuiltin<"__builtin_msa_ilvr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvr_h : GCCBuiltin<"__builtin_msa_ilvr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvr_w : GCCBuiltin<"__builtin_msa_ilvr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvr_d : GCCBuiltin<"__builtin_msa_ilvr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_insert_b : GCCBuiltin<"__builtin_msa_insert_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_h : GCCBuiltin<"__builtin_msa_insert_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_w : GCCBuiltin<"__builtin_msa_insert_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_d : GCCBuiltin<"__builtin_msa_insert_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; + +def int_mips_insve_b : GCCBuiltin<"__builtin_msa_insve_b">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_insve_h : GCCBuiltin<"__builtin_msa_insve_h">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_insve_w : GCCBuiltin<"__builtin_msa_insve_w">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_insve_d : GCCBuiltin<"__builtin_msa_insve_d">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_ld_b : GCCBuiltin<"__builtin_msa_ld_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_h : GCCBuiltin<"__builtin_msa_ld_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_w : GCCBuiltin<"__builtin_msa_ld_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_d : GCCBuiltin<"__builtin_msa_ld_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + +def int_mips_ldi_b : GCCBuiltin<"__builtin_msa_ldi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_h : GCCBuiltin<"__builtin_msa_ldi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_w : GCCBuiltin<"__builtin_msa_ldi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_d : GCCBuiltin<"__builtin_msa_ldi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem]>; + +// This instruction is part of the MSA spec but it does not share the +// __builtin_msa prefix because it operates on the GPR registers. +def int_mips_lsa : GCCBuiltin<"__builtin_mips_lsa">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_madd_q_h : GCCBuiltin<"__builtin_msa_madd_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_madd_q_w : GCCBuiltin<"__builtin_msa_madd_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_maddr_q_h : GCCBuiltin<"__builtin_msa_maddr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_maddr_q_w : GCCBuiltin<"__builtin_msa_maddr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_maddv_b : GCCBuiltin<"__builtin_msa_maddv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_maddv_h : GCCBuiltin<"__builtin_msa_maddv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_maddv_w : GCCBuiltin<"__builtin_msa_maddv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_maddv_d : GCCBuiltin<"__builtin_msa_maddv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_max_a_b : GCCBuiltin<"__builtin_msa_max_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_a_h : GCCBuiltin<"__builtin_msa_max_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_a_w : GCCBuiltin<"__builtin_msa_max_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_a_d : GCCBuiltin<"__builtin_msa_max_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_max_s_b : GCCBuiltin<"__builtin_msa_max_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_s_h : GCCBuiltin<"__builtin_msa_max_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_s_w : GCCBuiltin<"__builtin_msa_max_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_s_d : GCCBuiltin<"__builtin_msa_max_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_max_u_b : GCCBuiltin<"__builtin_msa_max_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_u_h : GCCBuiltin<"__builtin_msa_max_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_u_w : GCCBuiltin<"__builtin_msa_max_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_u_d : GCCBuiltin<"__builtin_msa_max_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_maxi_s_b : GCCBuiltin<"__builtin_msa_maxi_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_h : GCCBuiltin<"__builtin_msa_maxi_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_w : GCCBuiltin<"__builtin_msa_maxi_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_d : GCCBuiltin<"__builtin_msa_maxi_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_maxi_u_b : GCCBuiltin<"__builtin_msa_maxi_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_h : GCCBuiltin<"__builtin_msa_maxi_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_w : GCCBuiltin<"__builtin_msa_maxi_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_d : GCCBuiltin<"__builtin_msa_maxi_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_min_a_b : GCCBuiltin<"__builtin_msa_min_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_a_h : GCCBuiltin<"__builtin_msa_min_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_a_w : GCCBuiltin<"__builtin_msa_min_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_a_d : GCCBuiltin<"__builtin_msa_min_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_min_s_b : GCCBuiltin<"__builtin_msa_min_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_s_h : GCCBuiltin<"__builtin_msa_min_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_s_w : GCCBuiltin<"__builtin_msa_min_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_s_d : GCCBuiltin<"__builtin_msa_min_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_min_u_b : GCCBuiltin<"__builtin_msa_min_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_u_h : GCCBuiltin<"__builtin_msa_min_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_u_w : GCCBuiltin<"__builtin_msa_min_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_u_d : GCCBuiltin<"__builtin_msa_min_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_mini_s_b : GCCBuiltin<"__builtin_msa_mini_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_h : GCCBuiltin<"__builtin_msa_mini_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_w : GCCBuiltin<"__builtin_msa_mini_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_d : GCCBuiltin<"__builtin_msa_mini_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_mini_u_b : GCCBuiltin<"__builtin_msa_mini_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_h : GCCBuiltin<"__builtin_msa_mini_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_w : GCCBuiltin<"__builtin_msa_mini_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_d : GCCBuiltin<"__builtin_msa_mini_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_mod_s_b : GCCBuiltin<"__builtin_msa_mod_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mod_s_h : GCCBuiltin<"__builtin_msa_mod_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mod_s_w : GCCBuiltin<"__builtin_msa_mod_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mod_s_d : GCCBuiltin<"__builtin_msa_mod_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_mod_u_b : GCCBuiltin<"__builtin_msa_mod_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mod_u_h : GCCBuiltin<"__builtin_msa_mod_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mod_u_w : GCCBuiltin<"__builtin_msa_mod_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mod_u_d : GCCBuiltin<"__builtin_msa_mod_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_move_v : GCCBuiltin<"__builtin_msa_move_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_msub_q_h : GCCBuiltin<"__builtin_msa_msub_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msub_q_w : GCCBuiltin<"__builtin_msa_msub_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_msubr_q_h : GCCBuiltin<"__builtin_msa_msubr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msubr_q_w : GCCBuiltin<"__builtin_msa_msubr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_msubv_b : GCCBuiltin<"__builtin_msa_msubv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_msubv_h : GCCBuiltin<"__builtin_msa_msubv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msubv_w : GCCBuiltin<"__builtin_msa_msubv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_msubv_d : GCCBuiltin<"__builtin_msa_msubv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_mul_q_h : GCCBuiltin<"__builtin_msa_mul_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mul_q_w : GCCBuiltin<"__builtin_msa_mul_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_mulr_q_h : GCCBuiltin<"__builtin_msa_mulr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mulr_q_w : GCCBuiltin<"__builtin_msa_mulr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_mulv_b : GCCBuiltin<"__builtin_msa_mulv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mulv_h : GCCBuiltin<"__builtin_msa_mulv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mulv_w : GCCBuiltin<"__builtin_msa_mulv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mulv_d : GCCBuiltin<"__builtin_msa_mulv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nloc_b : GCCBuiltin<"__builtin_msa_nloc_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_nloc_h : GCCBuiltin<"__builtin_msa_nloc_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_nloc_w : GCCBuiltin<"__builtin_msa_nloc_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_nloc_d : GCCBuiltin<"__builtin_msa_nloc_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nlzc_b : GCCBuiltin<"__builtin_msa_nlzc_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_nlzc_h : GCCBuiltin<"__builtin_msa_nlzc_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_nlzc_w : GCCBuiltin<"__builtin_msa_nlzc_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_nlzc_d : GCCBuiltin<"__builtin_msa_nlzc_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nor_v : GCCBuiltin<"__builtin_msa_nor_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_nori_b : GCCBuiltin<"__builtin_msa_nori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_or_v : GCCBuiltin<"__builtin_msa_or_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_ori_b : GCCBuiltin<"__builtin_msa_ori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_pckev_b : GCCBuiltin<"__builtin_msa_pckev_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pckev_h : GCCBuiltin<"__builtin_msa_pckev_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pckev_w : GCCBuiltin<"__builtin_msa_pckev_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pckev_d : GCCBuiltin<"__builtin_msa_pckev_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_pckod_b : GCCBuiltin<"__builtin_msa_pckod_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pckod_h : GCCBuiltin<"__builtin_msa_pckod_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pckod_w : GCCBuiltin<"__builtin_msa_pckod_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pckod_d : GCCBuiltin<"__builtin_msa_pckod_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_pcnt_b : GCCBuiltin<"__builtin_msa_pcnt_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pcnt_h : GCCBuiltin<"__builtin_msa_pcnt_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pcnt_w : GCCBuiltin<"__builtin_msa_pcnt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pcnt_d : GCCBuiltin<"__builtin_msa_pcnt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_sat_s_b : GCCBuiltin<"__builtin_msa_sat_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_h : GCCBuiltin<"__builtin_msa_sat_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_w : GCCBuiltin<"__builtin_msa_sat_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_d : GCCBuiltin<"__builtin_msa_sat_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sat_u_b : GCCBuiltin<"__builtin_msa_sat_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_h : GCCBuiltin<"__builtin_msa_sat_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_w : GCCBuiltin<"__builtin_msa_sat_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_d : GCCBuiltin<"__builtin_msa_sat_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_shf_b : GCCBuiltin<"__builtin_msa_shf_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shf_h : GCCBuiltin<"__builtin_msa_shf_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shf_w : GCCBuiltin<"__builtin_msa_shf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sld_b : GCCBuiltin<"__builtin_msa_sld_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_h : GCCBuiltin<"__builtin_msa_sld_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_w : GCCBuiltin<"__builtin_msa_sld_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_d : GCCBuiltin<"__builtin_msa_sld_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sldi_b : GCCBuiltin<"__builtin_msa_sldi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_h : GCCBuiltin<"__builtin_msa_sldi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_w : GCCBuiltin<"__builtin_msa_sldi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_d : GCCBuiltin<"__builtin_msa_sldi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sll_b : GCCBuiltin<"__builtin_msa_sll_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_sll_h : GCCBuiltin<"__builtin_msa_sll_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_sll_w : GCCBuiltin<"__builtin_msa_sll_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_sll_d : GCCBuiltin<"__builtin_msa_sll_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_slli_b : GCCBuiltin<"__builtin_msa_slli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_h : GCCBuiltin<"__builtin_msa_slli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_w : GCCBuiltin<"__builtin_msa_slli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_d : GCCBuiltin<"__builtin_msa_slli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_splat_b : GCCBuiltin<"__builtin_msa_splat_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_h : GCCBuiltin<"__builtin_msa_splat_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_w : GCCBuiltin<"__builtin_msa_splat_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_d : GCCBuiltin<"__builtin_msa_splat_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_splati_b : GCCBuiltin<"__builtin_msa_splati_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_h : GCCBuiltin<"__builtin_msa_splati_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_w : GCCBuiltin<"__builtin_msa_splati_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_d : GCCBuiltin<"__builtin_msa_splati_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sra_b : GCCBuiltin<"__builtin_msa_sra_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_sra_h : GCCBuiltin<"__builtin_msa_sra_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_sra_w : GCCBuiltin<"__builtin_msa_sra_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_sra_d : GCCBuiltin<"__builtin_msa_sra_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srai_b : GCCBuiltin<"__builtin_msa_srai_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_h : GCCBuiltin<"__builtin_msa_srai_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_w : GCCBuiltin<"__builtin_msa_srai_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_d : GCCBuiltin<"__builtin_msa_srai_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srar_b : GCCBuiltin<"__builtin_msa_srar_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srar_h : GCCBuiltin<"__builtin_msa_srar_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srar_w : GCCBuiltin<"__builtin_msa_srar_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srar_d : GCCBuiltin<"__builtin_msa_srar_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srari_b : GCCBuiltin<"__builtin_msa_srari_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_h : GCCBuiltin<"__builtin_msa_srari_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_w : GCCBuiltin<"__builtin_msa_srari_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_d : GCCBuiltin<"__builtin_msa_srari_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srl_b : GCCBuiltin<"__builtin_msa_srl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srl_h : GCCBuiltin<"__builtin_msa_srl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srl_w : GCCBuiltin<"__builtin_msa_srl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srl_d : GCCBuiltin<"__builtin_msa_srl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srli_b : GCCBuiltin<"__builtin_msa_srli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_h : GCCBuiltin<"__builtin_msa_srli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_w : GCCBuiltin<"__builtin_msa_srli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_d : GCCBuiltin<"__builtin_msa_srli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srlr_b : GCCBuiltin<"__builtin_msa_srlr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srlr_h : GCCBuiltin<"__builtin_msa_srlr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srlr_w : GCCBuiltin<"__builtin_msa_srlr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srlr_d : GCCBuiltin<"__builtin_msa_srlr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srlri_b : GCCBuiltin<"__builtin_msa_srlri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_h : GCCBuiltin<"__builtin_msa_srlri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_w : GCCBuiltin<"__builtin_msa_srlri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_d : GCCBuiltin<"__builtin_msa_srlri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_st_b : GCCBuiltin<"__builtin_msa_st_b">, + Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_h : GCCBuiltin<"__builtin_msa_st_h">, + Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_w : GCCBuiltin<"__builtin_msa_st_w">, + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_d : GCCBuiltin<"__builtin_msa_st_d">, + Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +def int_mips_subs_s_b : GCCBuiltin<"__builtin_msa_subs_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subs_s_h : GCCBuiltin<"__builtin_msa_subs_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subs_s_w : GCCBuiltin<"__builtin_msa_subs_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subs_s_d : GCCBuiltin<"__builtin_msa_subs_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subs_u_b : GCCBuiltin<"__builtin_msa_subs_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subs_u_h : GCCBuiltin<"__builtin_msa_subs_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subs_u_w : GCCBuiltin<"__builtin_msa_subs_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subs_u_d : GCCBuiltin<"__builtin_msa_subs_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subsus_u_b : GCCBuiltin<"__builtin_msa_subsus_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subsus_u_h : GCCBuiltin<"__builtin_msa_subsus_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subsus_u_w : GCCBuiltin<"__builtin_msa_subsus_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subsus_u_d : GCCBuiltin<"__builtin_msa_subsus_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subsuu_s_b : GCCBuiltin<"__builtin_msa_subsuu_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subsuu_s_h : GCCBuiltin<"__builtin_msa_subsuu_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subsuu_s_w : GCCBuiltin<"__builtin_msa_subsuu_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subsuu_s_d : GCCBuiltin<"__builtin_msa_subsuu_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subv_b : GCCBuiltin<"__builtin_msa_subv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subv_h : GCCBuiltin<"__builtin_msa_subv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subv_w : GCCBuiltin<"__builtin_msa_subv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subv_d : GCCBuiltin<"__builtin_msa_subv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subvi_b : GCCBuiltin<"__builtin_msa_subvi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_h : GCCBuiltin<"__builtin_msa_subvi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_w : GCCBuiltin<"__builtin_msa_subvi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_d : GCCBuiltin<"__builtin_msa_subvi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_vshf_b : GCCBuiltin<"__builtin_msa_vshf_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_vshf_h : GCCBuiltin<"__builtin_msa_vshf_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_vshf_w : GCCBuiltin<"__builtin_msa_vshf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_vshf_d : GCCBuiltin<"__builtin_msa_vshf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_xor_v : GCCBuiltin<"__builtin_msa_xor_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_xori_b : GCCBuiltin<"__builtin_msa_xori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; } diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index c7675c2..4c5718f 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -206,6 +206,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_cvtsi642ss : GCCBuiltin<"__builtin_ia32_cvtsi642ss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">, Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_sse_cvttps2pi: GCCBuiltin<"__builtin_ia32_cvttps2pi">, @@ -936,9 +937,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse42_crc32_32_32 : GCCBuiltin<"__builtin_ia32_crc32si">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse42_crc32_64_8 : - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_sse42_crc32_64_64 : GCCBuiltin<"__builtin_ia32_crc32di">, Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; @@ -1635,7 +1633,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_vbroadcastss_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_avx2_vbroadcasti128 : - GCCBuiltin<"__builtin_ia32_vbroadcastsi256">, Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_x86_avx2_pbroadcastb_128 : GCCBuiltin<"__builtin_ia32_pbroadcastb128">, @@ -1867,6 +1864,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1891,6 +1896,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1915,6 +1928,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1939,6 +1960,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1957,6 +1986,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1975,6 +2012,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -2550,6 +2595,16 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// +// TBM + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_tbm_bextri_u32 : GCCBuiltin<"__builtin_ia32_bextri_u32">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_tbm_bextri_u64 : GCCBuiltin<"__builtin_ia32_bextri_u64">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// // RDRAND intrinsics - Return a random value and whether it is valid. // RDSEED intrinsics - Return a NIST SP800-90B & C compliant random value and // whether it is valid. @@ -2578,8 +2633,11 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">, Intrinsic<[llvm_i32_ty], [], []>; } -// AVX-512 +//===----------------------------------------------------------------------===// +// AVX512 + +// Mask ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Mask instructions // 16-bit mask @@ -2617,3 +2675,451 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; } + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_cvtss2usi : GCCBuiltin<"__builtin_ia32_cvtss2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtss2usi64 : GCCBuiltin<"__builtin_ia32_cvtss2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvttss2usi : GCCBuiltin<"__builtin_ia32_cvttss2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvttss2usi64 : GCCBuiltin<"__builtin_ia32_cvttss2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi2ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi642ss : GCCBuiltin<"__builtin_ia32_cvtusi642ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i64_ty], [IntrNoMem]>; + + def int_x86_avx512_cvtsd2usi : GCCBuiltin<"__builtin_ia32_cvtsd2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvtsd2usi64 : GCCBuiltin<"__builtin_ia32_cvtsd2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvttsd2usi : GCCBuiltin<"__builtin_ia32_cvttsd2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvttsd2usi64 : GCCBuiltin<"__builtin_ia32_cvttsd2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi2sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi642sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i64_ty], [IntrNoMem]>; + + def int_x86_avx512_vcvtph2ps_512 : GCCBuiltin<"__builtin_ia32_vcvtph2ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx512_vcvtps2ph_512 : GCCBuiltin<"__builtin_ia32_vcvtps2ph512">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty, llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector convert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_cvt_ps2dq_512 : GCCBuiltin<"__builtin_ia32_cvtps2dq512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtdq2_ps_512 : GCCBuiltin<"__builtin_ia32_cvtdq2ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty], [IntrNoMem]>; +} + +// Vector load with broadcast +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_vbroadcast_ss_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastss512">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx512_vbroadcast_ss_ps_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastss_ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + + def int_x86_avx512_vbroadcast_sd_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx512_vbroadcast_sd_pd_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd_pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + + def int_x86_avx512_pbroadcastd_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_pbroadcastd_i32_512 : + Intrinsic<[llvm_v16i32_ty], [llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_pbroadcastq_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_pbroadcastq_i64_512 : + Intrinsic<[llvm_v8i64_ty], [llvm_i64_ty], [IntrNoMem]>; +} + +// Vector sign and zero extend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i16_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty], + [IntrNoMem]>; +} + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_v8f64_ty], [IntrNoMem]>; + def int_x86_avx512_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_v8f64_ty], [IntrNoMem]>; + + def int_x86_avx512_pmaxu_d : GCCBuiltin<"__builtin_ia32_pmaxud512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxu_q : GCCBuiltin<"__builtin_ia32_pmaxuq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxs_d : GCCBuiltin<"__builtin_ia32_pmaxsd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxs_q : GCCBuiltin<"__builtin_ia32_pmaxsq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + + def int_x86_avx512_pminu_d : GCCBuiltin<"__builtin_ia32_pminud512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pminu_q : GCCBuiltin<"__builtin_ia32_pminuq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_pmins_d : GCCBuiltin<"__builtin_ia32_pminsd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmins_q : GCCBuiltin<"__builtin_ia32_pminsq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + + def int_x86_avx512_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtrndsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_rndscale_ps_512 : GCCBuiltin<"__builtin_ia32_rndscaleps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rndscale_pd_512 : GCCBuiltin<"__builtin_ia32_rndscalepd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], [IntrNoMem]>; + + def int_x86_avx512_rcp14_ps_512 : GCCBuiltin<"__builtin_ia32_rcp14ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_pd_512 : GCCBuiltin<"__builtin_ia32_rcp14pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_ss : GCCBuiltin<"__builtin_ia32_rcp14ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_sd : GCCBuiltin<"__builtin_ia32_rcp14sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt14ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt14pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_sd : GCCBuiltin<"__builtin_ia32_rsqrt14sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_rcp28_ps_512 : GCCBuiltin<"__builtin_ia32_rcp28ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_pd_512 : GCCBuiltin<"__builtin_ia32_rcp28pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt28ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt28pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi512_byteshift">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi512_byteshift">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Gather and Scatter ops +let TargetPrefix = "x86" in { + def int_x86_avx512_gather_dpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqps512">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherdpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dps_512 : GCCBuiltin<"__builtin_ia32_gatherdps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherqpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherqps512">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpi512">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gatherdpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_dpi_512 : GCCBuiltin<"__builtin_ia32_gatherdpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpq_512 : GCCBuiltin<"__builtin_ia32_gatherqpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpi_512 : GCCBuiltin<"__builtin_ia32_gatherqpi512">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; +// scatter + def int_x86_avx512_scatter_dpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterdpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dps_512 : GCCBuiltin<"__builtin_ia32_scatterdps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, llvm_v16f32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterqpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8f64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qps_512 : GCCBuiltin<"__builtin_ia32_scatterqps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8f32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, + llvm_v8i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpq_512 : GCCBuiltin<"__builtin_ia32_scatterdpq512">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], + []>; + def int_x86_avx512_scatter_dpi_512 : GCCBuiltin<"__builtin_ia32_scatterdpi512">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], + []>; + def int_x86_avx512_scatter_qpq_512 : GCCBuiltin<"__builtin_ia32_scatterqpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i32_ty], + []>; + def int_x86_avx512_scatter_qpi_512 : GCCBuiltin<"__builtin_ia32_scatterqpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i32_ty, + llvm_i32_ty], + []>; +} + +// AVX-512 conflict detection +let TargetPrefix = "x86" in { + def int_x86_avx512_conflict_d_512 : GCCBuiltin<"__builtin_ia32_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty], + []>; + def int_x86_avx512_conflict_d_mask_512 : + GCCBuiltin<"__builtin_ia32_mask_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i1_ty, llvm_v16i32_ty], + []>; + def int_x86_avx512_conflict_d_maskz_512: + GCCBuiltin<"__builtin_ia32_maskz_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i1_ty, llvm_v16i32_ty], + []>; + + def int_x86_avx512_conflict_q_512 : GCCBuiltin<"__builtin_ia32_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty], + []>; + def int_x86_avx512_conflict_q_mask_512 : + GCCBuiltin<"__builtin_ia32_mask_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i1_ty, llvm_v8i64_ty], + []>; + def int_x86_avx512_conflict_q_maskz_512: + GCCBuiltin<"__builtin_ia32_maskz_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i1_ty, llvm_v8i64_ty], + []>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mskblend_ps_512 : GCCBuiltin<"__builtin_ia32_mskblendps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16i1_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_mskblend_pd_512 : GCCBuiltin<"__builtin_ia32_mskblendpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8i1_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_mskblend_d_512 : GCCBuiltin<"__builtin_ia32_mskblendd512">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i1_ty, llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mskblend_q_512 : GCCBuiltin<"__builtin_ia32_mskblendq512">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8i64_ty], + [IntrNoMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { + def int_x86_avx512_cmpeq_pi_512 : GCCBuiltin<"__builtin_ia32_cmpeqpi512">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; + def int_x86_avx512_and_pi : GCCBuiltin<"__builtin_ia32_andpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SHA intrinsics +let TargetPrefix = "x86" in { + def int_x86_sha1rnds4 : GCCBuiltin<"__builtin_ia32_sha1rnds4">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sha1nexte : GCCBuiltin<"__builtin_ia32_sha1nexte">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha1msg1 : GCCBuiltin<"__builtin_ia32_sha1msg1">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha1msg2 : GCCBuiltin<"__builtin_ia32_sha1msg2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha256rnds2 : GCCBuiltin<"__builtin_ia32_sha256rnds2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sha256msg1 : GCCBuiltin<"__builtin_ia32_sha256msg1">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha256msg2 : GCCBuiltin<"__builtin_ia32_sha256msg2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +} diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h new file mode 100644 index 0000000..fa1436e --- /dev/null +++ b/include/llvm/IR/LegacyPassManager.h @@ -0,0 +1,111 @@ +//===- LegacyPassManager.h - Legacy Container for Passes --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the legacy PassManager class. This class is used to hold, +// maintain, and optimize execution of Passes. The PassManager class ensures +// that analysis results are available before a pass runs, and that Pass's are +// destroyed when the PassManager is destroyed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_LEGACYPASSMANAGER_H +#define LLVM_IR_LEGACYPASSMANAGER_H + +#include "llvm/Pass.h" +#include "llvm/Support/CBindingWrapping.h" + +namespace llvm { + +class Pass; +class Module; + +namespace legacy { + +class PassManagerImpl; +class FunctionPassManagerImpl; + +/// PassManagerBase - An abstract interface to allow code to add passes to +/// a pass manager without having to hard-code what kind of pass manager +/// it is. +class PassManagerBase { +public: + virtual ~PassManagerBase(); + + /// add - Add a pass to the queue of passes to run. This passes ownership of + /// the Pass to the PassManager. When the PassManager is destroyed, the pass + /// will be destroyed as well, so there is no need to delete the pass. This + /// implies that all passes MUST be allocated with 'new'. + virtual void add(Pass *P) = 0; +}; + +/// PassManager manages ModulePassManagers +class PassManager : public PassManagerBase { +public: + + PassManager(); + ~PassManager(); + + /// add - Add a pass to the queue of passes to run. This passes ownership of + /// the Pass to the PassManager. When the PassManager is destroyed, the pass + /// will be destroyed as well, so there is no need to delete the pass. This + /// implies that all passes MUST be allocated with 'new'. + void add(Pass *P); + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool run(Module &M); + +private: + /// PassManagerImpl_New is the actual class. PassManager is just the + /// wraper to publish simple pass manager interface + PassManagerImpl *PM; +}; + +/// FunctionPassManager manages FunctionPasses and BasicBlockPassManagers. +class FunctionPassManager : public PassManagerBase { +public: + /// FunctionPassManager ctor - This initializes the pass manager. It needs, + /// but does not take ownership of, the specified Module. + explicit FunctionPassManager(Module *M); + ~FunctionPassManager(); + + /// add - Add a pass to the queue of passes to run. This passes + /// ownership of the Pass to the PassManager. When the + /// PassManager_X is destroyed, the pass will be destroyed as well, so + /// there is no need to delete the pass. + /// This implies that all passes MUST be allocated with 'new'. + void add(Pass *P); + + /// run - Execute all of the passes scheduled for execution. Keep + /// track of whether any of the passes modifies the function, and if + /// so, return true. + /// + bool run(Function &F); + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(); + + /// doFinalization - Run all of the finalizers for the function passes. + /// + bool doFinalization(); + +private: + FunctionPassManagerImpl *FPM; + Module *M; +}; + +} // End legacy namespace + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_STDCXX_CONVERSION_FUNCTIONS(legacy::PassManagerBase, LLVMPassManagerRef) + +} // End llvm namespace + +#endif diff --git a/include/llvm/PassManagers.h b/include/llvm/IR/LegacyPassManagers.h index 7afb0a0..d256a3e 100644 --- a/include/llvm/PassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -1,4 +1,4 @@ -//===- llvm/PassManagers.h - Pass Infrastructure classes -------*- C++ -*-===// +//===- LegacyPassManagers.h - Legacy Pass Infrastructure --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index acd84d7..9659c2e 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -28,6 +28,10 @@ template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; +enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { + DEBUG_METADATA_VERSION = 1 // Current debug info version number. +}; + //===----------------------------------------------------------------------===// /// MDString - a single uniqued string. /// These are used to efficiently contain a byte sequence for metadata. @@ -161,6 +165,9 @@ public: return V->getValueID() == MDNodeVal; } + /// Check whether MDNode is a vtable access. + bool isTBAAVtableAccess() const; + /// Methods for metadata merging. static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 3dbc5ff..b30a9a3 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -391,7 +391,7 @@ public: /// @name Named Metadata Accessors /// @{ - /// getNamedMetadata - Return the NamedMDNode in the module with the + /// getNamedMetadata - Return the first NamedMDNode in the module with the /// specified name. This method returns null if a NamedMDNode with the /// specified name is not found. NamedMDNode *getNamedMetadata(const Twine &Name) const; diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 13ab72c..5b9bee7 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -439,8 +439,8 @@ public: /// offset of this GEP if the GEP is in fact constant. If the GEP is not /// all-constant, it returns false and the value of the offset APInt is /// undefined (it is *not* preserved!). The APInt passed into this routine - /// must be at least as wide as the IntPtr type for the address space of - /// the base GEP pointer. + /// must be at exactly as wide as the IntPtr type for the address space of the + /// base GEP pointer. bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { assert(Offset.getBitWidth() == DL.getPointerSizeInBits(getPointerAddressSpace()) && diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h new file mode 100644 index 0000000..833547a --- /dev/null +++ b/include/llvm/IR/PassManager.h @@ -0,0 +1,383 @@ +//===- PassManager.h - Pass management infrastructure -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header defines various interfaces for pass management in LLVM. There +/// is no "pass" interface in LLVM per se. Instead, an instance of any class +/// which supports a method to 'run' it over a unit of IR can be used as +/// a pass. A pass manager is generally a tool to collect a sequence of passes +/// which run over a particular IR construct, and run each of them in sequence +/// over each such construct in the containing IR construct. As there is no +/// containing IR construct for a Module, a manager for passes over modules +/// forms the base case which runs its managed passes in sequence over the +/// single module provided. +/// +/// The core IR library provides managers for running passes over +/// modules and functions. +/// +/// * FunctionPassManager can run over a Module, runs each pass over +/// a Function. +/// * ModulePassManager must be directly run, runs each pass over the Module. +/// +/// Note that the implementations of the pass managers use concept-based +/// polymorphism as outlined in the "Value Semantics and Concept-based +/// Polymorphism" talk (or its abbreviated sibling "Inheritance Is The Base +/// Class of Evil") by Sean Parent: +/// * http://github.com/sean-parent/sean-parent.github.com/wiki/Papers-and-Presentations +/// * http://www.youtube.com/watch?v=_BpMYeUFXv8 +/// * http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil +/// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/polymorphic_ptr.h" +#include "llvm/Support/type_traits.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include <list> +#include <vector> + +namespace llvm { + +class Module; +class Function; + +/// \brief Implementation details of the pass manager interfaces. +namespace detail { + +/// \brief Template for the abstract base class used to dispatch +/// polymorphically over pass objects. +template <typename T> struct PassConcept { + // Boiler plate necessary for the container of derived classes. + virtual ~PassConcept() {} + virtual PassConcept *clone() = 0; + + /// \brief The polymorphic API which runs the pass over a given IR entity. + virtual bool run(T Arg) = 0; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method +/// accepting a \c T. It requires the pass to be a copyable +/// object. +template <typename T, typename PassT> struct PassModel : PassConcept<T> { + PassModel(PassT Pass) : Pass(llvm_move(Pass)) {} + virtual PassModel *clone() { return new PassModel(Pass); } + virtual bool run(T Arg) { return Pass.run(Arg); } + PassT Pass; +}; + +} + +class AnalysisManager; + +class ModulePassManager { +public: + ModulePassManager(Module *M, AnalysisManager *AM = 0) : M(M), AM(AM) {} + + template <typename ModulePassT> void addPass(ModulePassT Pass) { + Passes.push_back(new ModulePassModel<ModulePassT>(llvm_move(Pass))); + } + + void run(); + +private: + // Pull in the concept type and model template specialized for modules. + typedef detail::PassConcept<Module *> ModulePassConcept; + template <typename PassT> + struct ModulePassModel : detail::PassModel<Module *, PassT> { + ModulePassModel(PassT Pass) : detail::PassModel<Module *, PassT>(Pass) {} + }; + + Module *M; + AnalysisManager *AM; + std::vector<polymorphic_ptr<ModulePassConcept> > Passes; +}; + +class FunctionPassManager { +public: + FunctionPassManager(AnalysisManager *AM = 0) : AM(AM) {} + + template <typename FunctionPassT> void addPass(FunctionPassT Pass) { + Passes.push_back(new FunctionPassModel<FunctionPassT>(llvm_move(Pass))); + } + + bool run(Module *M); + +private: + // Pull in the concept type and model template specialized for functions. + typedef detail::PassConcept<Function *> FunctionPassConcept; + template <typename PassT> + struct FunctionPassModel : detail::PassModel<Function *, PassT> { + FunctionPassModel(PassT Pass) + : detail::PassModel<Function *, PassT>(Pass) {} + }; + + AnalysisManager *AM; + std::vector<polymorphic_ptr<FunctionPassConcept> > Passes; +}; + + +/// \brief An analysis manager to coordinate and cache analyses run over +/// a module. +/// +/// The analysis manager is typically used by passes in a pass pipeline +/// (consisting potentially of several individual pass managers) over a module +/// of IR. It provides registration of available analyses, declaring +/// requirements on support for specific analyses, running of an specific +/// analysis over a specific unit of IR to compute an analysis result, and +/// caching of the analysis results to reuse them across multiple passes. +/// +/// It is the responsibility of callers to use the invalidation API to +/// invalidate analysis results when the IR they correspond to changes. The +/// \c ModulePassManager and \c FunctionPassManager do this automatically. +class AnalysisManager { +public: + AnalysisManager(Module *M) : M(M) {} + + /// \brief Get the result of an analysis pass for this module. + /// + /// If there is not a valid cached result in the manager already, this will + /// re-run the analysis to produce a valid result. + /// + /// The module passed in must be the same module as the analysis manager was + /// constructed around. + template <typename PassT> + const typename PassT::Result &getResult(Module *M) { + assert(ModuleAnalysisPasses.count(PassT::ID()) && + "This analysis pass was not registered prior to being queried"); + + const AnalysisResultConcept<Module> &ResultConcept = + getResultImpl(PassT::ID(), M); + typedef AnalysisResultModel<Module, typename PassT::Result> ResultModelT; + return static_cast<const ResultModelT &>(ResultConcept).Result; + } + + /// \brief Get the result of an analysis pass for a function. + /// + /// If there is not a valid cached result in the manager already, this will + /// re-run the analysis to produce a valid result. + template <typename PassT> + const typename PassT::Result &getResult(Function *F) { + assert(FunctionAnalysisPasses.count(PassT::ID()) && + "This analysis pass was not registered prior to being queried"); + + const AnalysisResultConcept<Function> &ResultConcept = + getResultImpl(PassT::ID(), F); + typedef AnalysisResultModel<Function, typename PassT::Result> ResultModelT; + return static_cast<const ResultModelT &>(ResultConcept).Result; + } + + /// \brief Register an analysis pass with the manager. + /// + /// This provides an initialized and set-up analysis pass to the + /// analysis + /// manager. Whomever is setting up analysis passes must use this to + /// populate + /// the manager with all of the analysis passes available. + template <typename PassT> void registerAnalysisPass(PassT Pass) { + registerAnalysisPassImpl<PassT>(llvm_move(Pass)); + } + + /// \brief Invalidate a specific analysis pass for an IR module. + /// + /// Note that the analysis result can disregard invalidation. + template <typename PassT> void invalidate(Module *M) { + invalidateImpl(PassT::ID(), M); + } + + /// \brief Invalidate a specific analysis pass for an IR function. + /// + /// Note that the analysis result can disregard invalidation. + template <typename PassT> void invalidate(Function *F) { + invalidateImpl(PassT::ID(), F); + } + + /// \brief Invalidate analyses cached for an IR Module. + /// + /// Note that specific analysis results can disregard invalidation by + /// overriding their invalidate method. + /// + /// The module must be the module this analysis manager was constructed + /// around. + void invalidateAll(Module *M); + + /// \brief Invalidate analyses cached for an IR Function. + /// + /// Note that specific analysis results can disregard invalidation by + /// overriding the invalidate method. + void invalidateAll(Function *F); + +private: + /// \brief Abstract concept of an analysis result. + /// + /// This concept is parameterized over the IR unit that this result pertains + /// to. + template <typename IRUnitT> struct AnalysisResultConcept { + virtual ~AnalysisResultConcept() {} + virtual AnalysisResultConcept *clone() = 0; + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer \c AnalysisManager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// \returns true if the result should indeed be invalidated (the default). + virtual bool invalidate(IRUnitT *IR) = 0; + }; + + /// \brief Wrapper to model the analysis result concept. + /// + /// Can wrap any type which implements a suitable invalidate member and model + /// the AnalysisResultConcept for the AnalysisManager. + template <typename IRUnitT, typename ResultT> + struct AnalysisResultModel : AnalysisResultConcept<IRUnitT> { + AnalysisResultModel(ResultT Result) : Result(llvm_move(Result)) {} + virtual AnalysisResultModel *clone() { + return new AnalysisResultModel(Result); + } + + /// \brief The model delegates to the \c ResultT method. + virtual bool invalidate(IRUnitT *IR) { return Result.invalidate(IR); } + + ResultT Result; + }; + + /// \brief Abstract concept of an analysis pass. + /// + /// This concept is parameterized over the IR unit that it can run over and + /// produce an analysis result. + template <typename IRUnitT> struct AnalysisPassConcept { + virtual ~AnalysisPassConcept() {} + virtual AnalysisPassConcept *clone() = 0; + + /// \brief Method to run this analysis over a unit of IR. + /// \returns The analysis result object to be queried by users, the caller + /// takes ownership. + virtual AnalysisResultConcept<IRUnitT> *run(IRUnitT *IR) = 0; + }; + + /// \brief Wrapper to model the analysis pass concept. + /// + /// Can wrap any type which implements a suitable \c run method. The method + /// must accept the IRUnitT as an argument and produce an object which can be + /// wrapped in a \c AnalysisResultModel. + template <typename PassT> + struct AnalysisPassModel : AnalysisPassConcept<typename PassT::IRUnitT> { + AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {} + virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); } + + // FIXME: Replace PassT::IRUnitT with type traits when we use C++11. + typedef typename PassT::IRUnitT IRUnitT; + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel<IRUnitT, typename PassT::Result> ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + virtual ResultModelT *run(IRUnitT *IR) { + return new ResultModelT(Pass.run(IR)); + } + + PassT Pass; + }; + + + /// \brief Get a module pass result, running the pass if necessary. + const AnalysisResultConcept<Module> &getResultImpl(void *PassID, Module *M); + + /// \brief Get a function pass result, running the pass if necessary. + const AnalysisResultConcept<Function> &getResultImpl(void *PassID, + Function *F); + + /// \brief Invalidate a module pass result. + void invalidateImpl(void *PassID, Module *M); + + /// \brief Invalidate a function pass result. + void invalidateImpl(void *PassID, Function *F); + + + /// \brief Module pass specific implementation of registration. + template <typename PassT> + typename enable_if<is_same<typename PassT::IRUnitT, Module> >::type + registerAnalysisPassImpl(PassT Pass) { + assert(!ModuleAnalysisPasses.count(PassT::ID()) && + "Registered the same analysis pass twice!"); + ModuleAnalysisPasses[PassT::ID()] = + new AnalysisPassModel<PassT>(llvm_move(Pass)); + } + + /// \brief Function pass specific implementation of registration. + template <typename PassT> + typename enable_if<is_same<typename PassT::IRUnitT, Function> >::type + registerAnalysisPassImpl(PassT Pass) { + assert(!FunctionAnalysisPasses.count(PassT::ID()) && + "Registered the same analysis pass twice!"); + FunctionAnalysisPasses[PassT::ID()] = + new AnalysisPassModel<PassT>(llvm_move(Pass)); + } + + + /// \brief Map type from module analysis pass ID to pass concept pointer. + typedef DenseMap<void *, polymorphic_ptr<AnalysisPassConcept<Module> > > + ModuleAnalysisPassMapT; + + /// \brief Collection of module analysis passes, indexed by ID. + ModuleAnalysisPassMapT ModuleAnalysisPasses; + + /// \brief Map type from module analysis pass ID to pass result concept pointer. + typedef DenseMap<void *, polymorphic_ptr<AnalysisResultConcept<Module> > > + ModuleAnalysisResultMapT; + + /// \brief Cache of computed module analysis results for this module. + ModuleAnalysisResultMapT ModuleAnalysisResults; + + + /// \brief Map type from function analysis pass ID to pass concept pointer. + typedef DenseMap<void *, polymorphic_ptr<AnalysisPassConcept<Function> > > + FunctionAnalysisPassMapT; + + /// \brief Collection of function analysis passes, indexed by ID. + FunctionAnalysisPassMapT FunctionAnalysisPasses; + + /// \brief List of function analysis pass IDs and associated concept pointers. + /// + /// Requires iterators to be valid across appending new entries and arbitrary + /// erases. Provides both the pass ID and concept pointer such that it is + /// half of a bijection and provides storage for the actual result concept. + typedef std::list< + std::pair<void *, polymorphic_ptr<AnalysisResultConcept<Function> > > > + FunctionAnalysisResultListT; + + /// \brief Map type from function pointer to our custom list type. + typedef DenseMap<Function *, FunctionAnalysisResultListT> FunctionAnalysisResultListMapT; + + /// \brief Map from function to a list of function analysis results. + /// + /// Provides linear time removal of all analysis results for a function and + /// the ultimate storage for a particular cached analysis result. + FunctionAnalysisResultListMapT FunctionAnalysisResultLists; + + /// \brief Map type from a pair of analysis ID and function pointer to an + /// iterator into a particular result list. + typedef DenseMap<std::pair<void *, Function *>, + FunctionAnalysisResultListT::iterator> + FunctionAnalysisResultMapT; + + /// \brief Map from an analysis ID and function to a particular cached + /// analysis result. + FunctionAnalysisResultMapT FunctionAnalysisResults; + + /// \brief Module handle for the \c AnalysisManager. + Module *M; +}; + +} diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index 1bf8789..3cfb84e 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -324,6 +324,14 @@ public: subtype_iterator subtype_begin() const { return ContainedTys; } subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + typedef std::reverse_iterator<subtype_iterator> subtype_reverse_iterator; + subtype_reverse_iterator subtype_rbegin() const { + return subtype_reverse_iterator(subtype_end()); + } + subtype_reverse_iterator subtype_rend() const { + return subtype_reverse_iterator(subtype_begin()); + } + /// getContainedType - This method is used to implement the type iterator /// (defined a the end of the file). For derived types, this returns the /// types 'contained' in the derived type. diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 5fba3d5..e1361fe 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -22,26 +22,29 @@ namespace llvm { -class Constant; +class APInt; class Argument; -class Instruction; +class AssemblyAnnotationWriter; class BasicBlock; -class GlobalValue; +class Constant; +class DataLayout; class Function; -class GlobalVariable; class GlobalAlias; +class GlobalValue; +class GlobalVariable; class InlineAsm; -class ValueSymbolTable; -template<typename ValueTy> class StringMapEntry; -typedef StringMapEntry<Value*> ValueName; -class raw_ostream; -class AssemblyAnnotationWriter; -class ValueHandleBase; +class Instruction; class LLVMContext; -class Twine; class MDNode; -class Type; class StringRef; +class Twine; +class Type; +class ValueHandleBase; +class ValueSymbolTable; +class raw_ostream; + +template<typename ValueTy> class StringMapEntry; +typedef StringMapEntry<Value*> ValueName; //===----------------------------------------------------------------------===// // Value Class @@ -260,37 +263,53 @@ public: /// this value. bool hasValueHandle() const { return HasValueHandle; } - /// \brief This method strips off any unneeded pointer casts, - /// all-zero GEPs and aliases from the specified value, returning the original - /// uncasted value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off any unneeded pointer casts, all-zero GEPs and aliases + /// from the specified value, returning the original uncasted value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripPointerCasts(); const Value *stripPointerCasts() const { return const_cast<Value*>(this)->stripPointerCasts(); } - /// \brief This method strips off any unneeded pointer casts and - /// all-zero GEPs from the specified value, returning the original - /// uncasted value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off any unneeded pointer casts and all-zero GEPs from the + /// specified value, returning the original uncasted value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripPointerCastsNoFollowAliases(); const Value *stripPointerCastsNoFollowAliases() const { return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases(); } - /// stripInBoundsConstantOffsets - This method strips off unneeded pointer casts and - /// all-constant GEPs from the specified value, returning the original - /// pointer value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off unneeded pointer casts and all-constant GEPs from the + /// specified value, returning the original pointer value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripInBoundsConstantOffsets(); const Value *stripInBoundsConstantOffsets() const { return const_cast<Value*>(this)->stripInBoundsConstantOffsets(); } - /// stripInBoundsOffsets - This method strips off unneeded pointer casts and - /// any in-bounds Offsets from the specified value, returning the original - /// pointer value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips like \c stripInBoundsConstantOffsets but also accumulates + /// the constant offset stripped. + /// + /// Stores the resulting constant offset stripped into the APInt provided. + /// The provided APInt will be extended or truncated as needed to be the + /// correct bitwidth for an offset of this pointer type. + /// + /// If this is called on a non-pointer value, it returns 'this'. + Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, + APInt &Offset); + const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, + APInt &Offset) const { + return const_cast<Value *>(this) + ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset); + } + + /// \brief Strips off unneeded pointer casts and any in-bounds offsets from + /// the specified value, returning the original pointer value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripInBoundsOffsets(); const Value *stripInBoundsOffsets() const { return const_cast<Value*>(this)->stripInBoundsOffsets(); diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index d7d18d0..aefb3c0 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -70,13 +70,13 @@ void initializeAliasDebuggerPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlwaysInlinerPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); +void initializeSampleProfileLoaderPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); -void initializeBasicCallGraphPass(PassRegistry&); +void initializeCallGraphPass(PassRegistry&); void initializeBasicTTIPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); -void initializeBlockPlacementPass(PassRegistry&); void initializeBoundsCheckingPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoPass(PassRegistry&); @@ -90,8 +90,6 @@ void initializeCFGSimplifyPassPass(PassRegistry&); void initializeFlattenCFGPassPass(PassRegistry&); void initializeStructurizeCFGPass(PassRegistry&); void initializeCFGViewerPass(PassRegistry&); -void initializeCalculateSpillWeightsPass(PassRegistry&); -void initializeCallGraphAnalysisGroup(PassRegistry&); void initializeCodeGenPreparePass(PassRegistry&); void initializeConstantMergePass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&); @@ -105,6 +103,7 @@ void initializeDSEPass(PassRegistry&); void initializeDebugIRPass(PassRegistry&); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); +void initializeDelinearizationPass(PassRegistry &); void initializeDependenceAnalysisPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); @@ -114,14 +113,13 @@ void initializeDominanceFrontierPass(PassRegistry&); void initializeDominatorTreePass(PassRegistry&); void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); -void initializeEdgeProfilerPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); -void initializePathProfilerPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); void initializeThreadSanitizerPass(PassRegistry&); +void initializeDataFlowSanitizerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFindUsedTypesPass(PassRegistry&); @@ -155,8 +153,6 @@ void initializeLiveRegMatrixPass(PassRegistry&); void initializeLiveStacksPass(PassRegistry&); void initializeLiveVariablesPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); -void initializeProfileMetadataLoaderPassPass(PassRegistry&); -void initializePathProfileLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLoopDeletionPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); @@ -166,6 +162,7 @@ void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); void initializeLoopStrengthReducePass(PassRegistry&); void initializeGlobalMergePass(PassRegistry&); +void initializeLoopRerollPass(PassRegistry&); void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); void initializeLoopIdiomRecognizePass(PassRegistry&); @@ -195,15 +192,13 @@ void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); void initializeNoAAPass(PassRegistry&); -void initializeNoProfileInfoPass(PassRegistry&); -void initializeNoPathProfileInfoPass(PassRegistry&); void initializeObjCARCAliasAnalysisPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCExpandPass(PassRegistry&); void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCOptPass(PassRegistry&); -void initializeOptimalEdgeProfilerPass(PassRegistry&); void initializeOptimizePHIsPass(PassRegistry&); +void initializePartiallyInlineLibCallsPass(PassRegistry&); void initializePEIPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&); void initializePartialInlinerPass(PassRegistry&); @@ -219,11 +214,6 @@ void initializePrintFunctionPassPass(PassRegistry&); void initializePrintModulePassPass(PassRegistry&); void initializePrintBasicBlockPassPass(PassRegistry&); void initializeProcessImplicitDefsPass(PassRegistry&); -void initializeProfileEstimatorPassPass(PassRegistry&); -void initializeProfileInfoAnalysisGroup(PassRegistry&); -void initializePathProfileInfoAnalysisGroup(PassRegistry&); -void initializePathProfileVerifierPass(PassRegistry&); -void initializeProfileVerifierPassPass(PassRegistry&); void initializePromotePassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); void initializeReassociatePass(PassRegistry&); @@ -253,7 +243,6 @@ void initializeStripDeadPrototypesPassPass(PassRegistry&); void initializeStripDebugDeclarePass(PassRegistry&); void initializeStripNonDebugSymbolsPass(PassRegistry&); void initializeStripSymbolsPass(PassRegistry&); -void initializeStrongPHIEliminationPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); diff --git a/include/llvm/InstVisitor.h b/include/llvm/InstVisitor.h index 2911703..de7206d 100644 --- a/include/llvm/InstVisitor.h +++ b/include/llvm/InstVisitor.h @@ -191,6 +191,7 @@ public: RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst);} RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);} RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);} + RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);} RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction);} RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(UnaryInstruction);} RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h new file mode 100644 index 0000000..c478bd9 --- /dev/null +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -0,0 +1,153 @@ +//===-LTOCodeGenerator.h - LLVM Link Time Optimizer -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the LTOCodeGenerator class. +// +// LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO. +// +// The Pre-IPO phase compiles source code into bitcode file. The resulting +// bitcode files, along with object files and libraries, will be fed to the +// linker to through the IPO and Post-IPO phases. By using obj-file extension, +// the resulting bitcode file disguises itself as an object file, and therefore +// obviates the need of writing a special set of the make-rules only for LTO +// compilation. +// +// The IPO phase perform inter-procedural analyses and optimizations, and +// the Post-IPO consists two sub-phases: intra-procedural scalar optimizations +// (SOPT), and intra-procedural target-dependent code generator (CG). +// +// As of this writing, we don't separate IPO and the Post-IPO SOPT. They +// are intermingled together, and are driven by a single pass manager (see +// PassManagerBuilder::populateLTOPassManager()). +// +// The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages. +// The "CodeGenerator" here is bit confusing. Don't confuse the "CodeGenerator" +// with the machine specific code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef LTO_CODE_GENERATOR_H +#define LTO_CODE_GENERATOR_H + +#include "llvm-c/lto.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Linker.h" +#include "llvm/Target/TargetOptions.h" +#include <string> +#include <vector> + +namespace llvm { + class LLVMContext; + class GlobalValue; + class Mangler; + class MemoryBuffer; + class TargetLibraryInfo; + class TargetMachine; + class raw_ostream; +} + +//===----------------------------------------------------------------------===// +/// LTOCodeGenerator - C++ class which implements the opaque lto_code_gen_t +/// type. +/// +struct LTOCodeGenerator { + static const char *getVersionString(); + + LTOCodeGenerator(); + ~LTOCodeGenerator(); + + // Merge given module, return true on success. + bool addModule(struct LTOModule*, std::string &errMsg); + + void setTargetOptions(llvm::TargetOptions options); + void setDebugInfo(lto_debug_model); + void setCodePICModel(lto_codegen_model); + + void setCpu(const char *mCpu) { MCpu = mCpu; } + + void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } + + // To pass options to the driver and optimization passes. These options are + // not necessarily for debugging purpose (The function name is misleading). + // This function should be called before LTOCodeGenerator::compilexxx(), + // and LTOCodeGenerator::writeMergedModules(). + // + void setCodeGenDebugOptions(const char *opts); + + // Parse the options set in setCodeGenDebugOptions. Like + // setCodeGenDebugOptions, this must be called before + // LTOCodeGenerator::compilexxx() and LTOCodeGenerator::writeMergedModules() + void parseCodeGenDebugOptions(); + + // Write the merged module to the file specified by the given path. + // Return true on success. + bool writeMergedModules(const char *path, std::string &errMsg); + + // Compile the merged module into a *single* object file; the path to object + // file is returned to the caller via argument "name". Return true on + // success. + // + // NOTE that it is up to the linker to remove the intermediate object file. + // Do not try to remove the object file in LTOCodeGenerator's destructor + // as we don't who (LTOCodeGenerator or the obj file) will last longer. + // + bool compile_to_file(const char **name, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + + // As with compile_to_file(), this function compiles the merged module into + // single object file. Instead of returning the object-file-path to the caller + // (linker), it brings the object to a buffer, and return the buffer to the + // caller. This function should delete intermediate object file once its content + // is brought to memory. Return NULL if the compilation was not successful. + // + const void *compile(size_t *length, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + +private: + void initializeLTOPasses(); + + bool generateObjectFile(llvm::raw_ostream &out, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + void applyScopeRestrictions(); + void applyRestriction(llvm::GlobalValue &GV, + const llvm::ArrayRef<llvm::StringRef> &Libcalls, + std::vector<const char*> &MustPreserveList, + llvm::SmallPtrSet<llvm::GlobalValue*, 8> &AsmUsed, + llvm::Mangler &Mangler); + bool determineTarget(std::string &errMsg); + + typedef llvm::StringMap<uint8_t> StringSet; + + llvm::LLVMContext &Context; + llvm::Linker Linker; + llvm::TargetMachine *TargetMach; + bool EmitDwarfDebugInfo; + bool ScopeRestrictionsDone; + lto_codegen_model CodeModel; + StringSet MustPreserveSymbols; + StringSet AsmUndefinedRefs; + llvm::MemoryBuffer *NativeObjectFile; + std::vector<char *> CodegenOptions; + std::string MCpu; + std::string NativeObjectPath; + llvm::TargetOptions Options; +}; + +#endif // LTO_CODE_GENERATOR_H diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/LTOModule.h new file mode 100644 index 0000000..f4693c8 --- /dev/null +++ b/include/llvm/LTO/LTOModule.h @@ -0,0 +1,196 @@ +//===-LTOModule.h - LLVM Link Time Optimizer ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the LTOModule class. +// +//===----------------------------------------------------------------------===// + +#ifndef LTO_MODULE_H +#define LTO_MODULE_H + +#include "llvm-c/lto.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetMachine.h" +#include <string> +#include <vector> + +// Forward references to llvm classes. +namespace llvm { + class Function; + class GlobalValue; + class MemoryBuffer; + class TargetOptions; + class Value; +} + +//===----------------------------------------------------------------------===// +/// LTOModule - C++ class which implements the opaque lto_module_t type. +/// +struct LTOModule { +private: + typedef llvm::StringMap<uint8_t> StringSet; + + struct NameAndAttributes { + const char *name; + uint32_t attributes; + bool isFunction; + const llvm::GlobalValue *symbol; + }; + + llvm::OwningPtr<llvm::Module> _module; + llvm::OwningPtr<llvm::TargetMachine> _target; + std::vector<NameAndAttributes> _symbols; + + // _defines and _undefines only needed to disambiguate tentative definitions + StringSet _defines; + llvm::StringMap<NameAndAttributes> _undefines; + std::vector<const char*> _asm_undefines; + llvm::MCContext _context; + + // Use mangler to add GlobalPrefix to names to match linker names. + llvm::Mangler _mangler; + + LTOModule(llvm::Module *m, llvm::TargetMachine *t); +public: + /// isBitcodeFile - Returns 'true' if the file or memory contents is LLVM + /// bitcode. + static bool isBitcodeFile(const void *mem, size_t length); + static bool isBitcodeFile(const char *path); + + /// isBitcodeFileForTarget - Returns 'true' if the file or memory contents + /// is LLVM bitcode for the specified triple. + static bool isBitcodeFileForTarget(const void *mem, + size_t length, + const char *triplePrefix); + static bool isBitcodeFileForTarget(const char *path, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule. N.B. These methods take ownership + /// of the buffer. The caller must have initialized the Targets, the + /// TargetMCs, the AsmPrinters, and the AsmParsers by calling: + /// + /// InitializeAllTargets(); + /// InitializeAllTargetMCs(); + /// InitializeAllAsmPrinters(); + /// InitializeAllAsmParsers(); + static LTOModule *makeLTOModule(const char* path, + llvm::TargetOptions options, + std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + size_t size, llvm::TargetOptions options, + std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + size_t map_size, + off_t offset, llvm::TargetOptions options, + std::string& errMsg); + static LTOModule *makeLTOModule(const void *mem, size_t length, + llvm::TargetOptions options, + std::string &errMsg); + + /// getTargetTriple - Return the Module's target triple. + const char *getTargetTriple() { + return _module->getTargetTriple().c_str(); + } + + /// setTargetTriple - Set the Module's target triple. + void setTargetTriple(const char *triple) { + _module->setTargetTriple(triple); + } + + /// getSymbolCount - Get the number of symbols + uint32_t getSymbolCount() { + return _symbols.size(); + } + + /// getSymbolAttributes - Get the attributes for a symbol at the specified + /// index. + lto_symbol_attributes getSymbolAttributes(uint32_t index) { + if (index < _symbols.size()) + return lto_symbol_attributes(_symbols[index].attributes); + return lto_symbol_attributes(0); + } + + /// getSymbolName - Get the name of the symbol at the specified index. + const char *getSymbolName(uint32_t index) { + if (index < _symbols.size()) + return _symbols[index].name; + return NULL; + } + + /// getLLVVMModule - Return the Module. + llvm::Module *getLLVVMModule() { return _module.get(); } + + /// getAsmUndefinedRefs - + const std::vector<const char*> &getAsmUndefinedRefs() { + return _asm_undefines; + } + +private: + /// parseSymbols - Parse the symbols from the module and model-level ASM and + /// add them to either the defined or undefined lists. + bool parseSymbols(std::string &errMsg); + + /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet + /// to a list to be resolved later. + void addPotentialUndefinedSymbol(const llvm::GlobalValue *dcl, bool isFunc); + + /// addDefinedSymbol - Add a defined symbol to the list. + void addDefinedSymbol(const llvm::GlobalValue *def, bool isFunction); + + /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. + void addDefinedFunctionSymbol(const llvm::Function *f); + + /// addDefinedDataSymbol - Add a data symbol as defined to the list. + void addDefinedDataSymbol(const llvm::GlobalValue *v); + + /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the + /// defined or undefined lists. + bool addAsmGlobalSymbols(std::string &errMsg); + + /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the + /// defined list. + void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope); + + /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to + /// the undefined list. + void addAsmGlobalSymbolUndef(const char *); + + /// addObjCClass - Parse i386/ppc ObjC class data structure. + void addObjCClass(const llvm::GlobalVariable *clgv); + + /// addObjCCategory - Parse i386/ppc ObjC category data structure. + void addObjCCategory(const llvm::GlobalVariable *clgv); + + /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. + void addObjCClassRef(const llvm::GlobalVariable *clgv); + + /// objcClassNameFromExpression - Get string that the data pointer points + /// to. + bool objcClassNameFromExpression(const llvm::Constant* c, std::string &name); + + /// isTargetMatch - Returns 'true' if the memory buffer is for the specified + /// target triple. + static bool isTargetMatch(llvm::MemoryBuffer *memBuffer, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule (private version). N.B. This + /// method takes ownership of the buffer. + static LTOModule *makeLTOModule(llvm::MemoryBuffer *buffer, + llvm::TargetOptions options, + std::string &errMsg); + + /// makeBuffer - Create a MemoryBuffer from a memory range. + static llvm::MemoryBuffer *makeBuffer(const void *mem, size_t length); +}; + +#endif // LTO_MODULE_H diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index ec39829..8183fa2 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -56,7 +56,6 @@ namespace { (void) llvm::createLibCallAliasAnalysisPass(0); (void) llvm::createScalarEvolutionAliasAnalysisPass(); (void) llvm::createTypeBasedAliasAnalysisPass(); - (void) llvm::createBlockPlacementPass(); (void) llvm::createBoundsCheckingPass(); (void) llvm::createBreakCriticalEdgesPass(); (void) llvm::createCallGraphPrinterPass(); @@ -75,9 +74,6 @@ namespace { (void) llvm::createDomPrinterPass(); (void) llvm::createDomOnlyViewerPass(); (void) llvm::createDomViewerPass(); - (void) llvm::createEdgeProfilerPass(); - (void) llvm::createOptimalEdgeProfilerPass(); - (void) llvm::createPathProfilerPass(); (void) llvm::createGCOVProfilerPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); @@ -95,6 +91,7 @@ namespace { (void) llvm::createLoopExtractorPass(); (void) llvm::createLoopSimplifyPass(); (void) llvm::createLoopStrengthReducePass(); + (void) llvm::createLoopRerollPass(); (void) llvm::createLoopUnrollPass(); (void) llvm::createLoopUnswitchPass(); (void) llvm::createLoopIdiomPass(); @@ -103,18 +100,11 @@ namespace { (void) llvm::createLowerInvokePass(); (void) llvm::createLowerSwitchPass(); (void) llvm::createNoAAPass(); - (void) llvm::createNoProfileInfoPass(); (void) llvm::createObjCARCAliasAnalysisPass(); (void) llvm::createObjCARCAPElimPass(); (void) llvm::createObjCARCExpandPass(); (void) llvm::createObjCARCContractPass(); (void) llvm::createObjCARCOptPass(); - (void) llvm::createProfileEstimatorPass(); - (void) llvm::createProfileVerifierPass(); - (void) llvm::createPathProfileVerifierPass(); - (void) llvm::createProfileLoaderPass(); - (void) llvm::createProfileMetadataLoaderPass(); - (void) llvm::createPathProfileLoaderPass(); (void) llvm::createPromoteMemoryToRegisterPass(); (void) llvm::createDemoteRegisterToMemoryPass(); (void) llvm::createPruneEHPass(); @@ -163,6 +153,7 @@ namespace { (void) llvm::createLoopVectorizePass(); (void) llvm::createSLPVectorizerPass(); (void) llvm::createBBVectorizePass(); + (void) llvm::createPartiallyInlineLibCallsPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); diff --git a/include/llvm/Linker.h b/include/llvm/Linker.h index 3667b85..4f37459 100644 --- a/include/llvm/Linker.h +++ b/include/llvm/Linker.h @@ -32,7 +32,9 @@ class Linker { Linker(Module *M); ~Linker(); + Module *getModule() const { return Composite; } + void deleteModule(); /// \brief Link \p Src into the composite. The source is destroyed if /// \p Mode is DestroySource and preserved if it is PreserveSource. diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 9a6b703..f946f41 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -10,7 +10,9 @@ #ifndef LLVM_MC_MCASMBACKEND_H #define LLVM_MC_MCASMBACKEND_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCFixup.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -32,6 +34,7 @@ class raw_ostream; class MCAsmBackend { MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION; void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION; + protected: // Can only create subclasses. MCAsmBackend(); @@ -42,7 +45,7 @@ public: virtual ~MCAsmBackend(); /// lifetime management - virtual void reset() { } + virtual void reset() {} /// createObjectWriter - Create a new MCObjectWriter instance for use by the /// assembler backend to emit the final object file. @@ -50,7 +53,7 @@ public: /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable /// non-standard ELFObjectWriters. - virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { llvm_unreachable("createELFObjectTargetWriter is not supported by asm " "backend"); } @@ -71,9 +74,7 @@ public: /// hasDataInCodeSupport - Check whether this target implements data-in-code /// markers. If not, data region directives will be ignored. - bool hasDataInCodeSupport() const { - return HasDataInCodeSupport; - } + bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } /// doesSectionRequireSymbols - Check whether the given section requires that /// all symbols (even temporaries) have symbol table entries. @@ -128,8 +129,7 @@ public: /// fixupNeedsRelaxation - Target specific predicate for whether a given /// fixup requires the associated instruction to be relaxed. - virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, - uint64_t Value, + virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; @@ -160,6 +160,12 @@ public: /// handleAssemblerFlag - Handle any target-specific assembler flags. /// By default, do nothing. virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} + + /// \brief Generate the compact unwind encoding for the CFI instructions. + virtual uint32_t + generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const { + return 0; + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index e83b624..7a99394 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -93,9 +93,9 @@ namespace llvm { /// this value. Factored out in .debug_frame and .debug_line. unsigned MinInstAlignment; // Defaults to 1. - /// PCSymbol - The symbol used to represent the current PC. Used in PC - /// relative expressions. - const char *PCSymbol; // Defaults to "$". + /// DollarIsPC - The '$' token, when not referencing an identifier or + /// constant, refers to the current PC. + bool DollarIsPC; // Defaults to false. /// SeparatorString - This string, if specified, is used to separate /// instructions from each other when on the same line. @@ -144,21 +144,9 @@ namespace llvm { /// AssemblerDialect - Which dialect of an assembler variant to use. unsigned AssemblerDialect; // Defaults to 0 - /// AllowQuotesInName - This is true if the assembler allows for complex - /// symbol names to be surrounded in quotes. This defaults to false. - bool AllowQuotesInName; - - /// AllowNameToStartWithDigit - This is true if the assembler allows symbol - /// names to start with a digit (e.g., "0x0021"). This defaults to false. - bool AllowNameToStartWithDigit; - - /// AllowPeriodsInName - This is true if the assembler allows periods in - /// symbol names. This defaults to true. - bool AllowPeriodsInName; - - /// AllowUTF8 - This is true if the assembler accepts UTF-8 input. - // FIXME: Make this a more general encoding setting? - bool AllowUTF8; + /// \brief This is true if the assembler allows @ characters in symbol + /// names. Defaults to false. + bool AllowAtInName; /// UseDataRegionDirectives - This is true if data region markers should /// be printed as ".data_region/.end_data_region" directives. If false, @@ -240,11 +228,6 @@ namespace llvm { /// const char *GlobalDirective; // Defaults to NULL. - /// ExternDirective - This is the directive used to declare external - /// globals. - /// - const char *ExternDirective; // Defaults to NULL. - /// HasSetDirective - True if the assembler supports the .set directive. bool HasSetDirective; // Defaults to true. @@ -271,14 +254,14 @@ namespace llvm { /// .file directive, this is true for ELF targets. bool HasSingleParameterDotFile; // Defaults to true. + /// hasIdentDirective - True if the target has a .ident directive, this is + /// true for ELF targets. + bool HasIdentDirective; // Defaults to false. + /// HasNoDeadStrip - True if this target supports the MachO .no_dead_strip /// directive. bool HasNoDeadStrip; // Defaults to false. - /// HasSymbolResolver - True if this target supports the MachO - /// .symbol_resolver directive. - bool HasSymbolResolver; // Defaults to false. - /// WeakRefDirective - This directive, if non-null, is used to declare a /// global as being a weak undefined symbol. const char *WeakRefDirective; // Defaults to NULL. @@ -316,10 +299,6 @@ namespace llvm { /// SupportsExceptionHandling - True if target supports exception handling. ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None - /// DwarfUsesInlineInfoSection - True if DwarfDebugInlineSection is used to - /// encode inline subroutine information. - bool DwarfUsesInlineInfoSection; // Defaults to false. - /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally /// uses relocations for references to other .debug_* sections. bool DwarfUsesRelocationsAcrossSections; @@ -429,8 +408,8 @@ namespace llvm { unsigned getMinInstAlignment() const { return MinInstAlignment; } - const char *getPCSymbol() const { - return PCSymbol; + bool getDollarIsPC() const { + return DollarIsPC; } const char *getSeparatorString() const { return SeparatorString; @@ -476,17 +455,8 @@ namespace llvm { unsigned getAssemblerDialect() const { return AssemblerDialect; } - bool doesAllowQuotesInName() const { - return AllowQuotesInName; - } - bool doesAllowNameToStartWithDigit() const { - return AllowNameToStartWithDigit; - } - bool doesAllowPeriodsInName() const { - return AllowPeriodsInName; - } - bool doesAllowUTF8() const { - return AllowUTF8; + bool doesAllowAtInName() const { + return AllowAtInName; } bool doesSupportDataRegionDirectives() const { return UseDataRegionDirectives; @@ -512,9 +482,6 @@ namespace llvm { const char *getGlobalDirective() const { return GlobalDirective; } - const char *getExternDirective() const { - return ExternDirective; - } bool hasSetDirective() const { return HasSetDirective; } bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; @@ -527,8 +494,8 @@ namespace llvm { } bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } - bool hasSymbolResolver() const { return HasSymbolResolver; } const char *getWeakRefDirective() const { return WeakRefDirective; } const char *getWeakDefDirective() const { return WeakDefDirective; } const char *getLinkOnceDirective() const { return LinkOnceDirective; } @@ -558,9 +525,6 @@ namespace llvm { ExceptionsType == ExceptionHandling::ARM || ExceptionsType == ExceptionHandling::Win64); } - bool doesDwarfUseInlineInfoSection() const { - return DwarfUsesInlineInfoSection; - } bool doesDwarfUseRelocationsAcrossSections() const { return DwarfUsesRelocationsAcrossSections; } diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h new file mode 100644 index 0000000..27fea84 --- /dev/null +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -0,0 +1,23 @@ +//===-- llvm/MC/MCAsmInfoELF.h - ELF Asm info -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFOELF_H +#define LLVM_MC_MCASMINFOELF_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { +class MCAsmInfoELF : public MCAsmInfo { + virtual void anchor(); +protected: + MCAsmInfoELF(); +}; +} + +#endif diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 2c8c602..0cf2b1d 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -19,6 +19,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" +#include <algorithm> #include <vector> // FIXME: Shouldn't be needed. namespace mcld { @@ -824,6 +825,9 @@ public: typedef SymbolDataListType::const_iterator const_symbol_iterator; typedef SymbolDataListType::iterator symbol_iterator; + typedef std::vector<std::string> FileNameVectorType; + typedef FileNameVectorType::const_iterator const_file_name_iterator; + typedef std::vector<IndirectSymbolData>::const_iterator const_indirect_symbol_iterator; typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; @@ -867,6 +871,9 @@ private: /// The list of linker options to propagate into the object file. std::vector<std::vector<std::string> > LinkerOptions; + /// List of declared file names + FileNameVectorType FileNames; + /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -1162,6 +1169,20 @@ public: return *Entry; } + const_file_name_iterator file_names_begin() const { + return FileNames.begin(); + } + + const_file_name_iterator file_names_end() const { + return FileNames.end(); + } + + void addFileName(StringRef FileName) { + if (std::find(file_names_begin(), file_names_end(), FileName) == + file_names_end()) + FileNames.push_back(FileName); + } + /// @} void dump(); diff --git a/include/llvm/MC/MCAtom.h b/include/llvm/MC/MCAtom.h index 6a93798..eab32d6 100644 --- a/include/llvm/MC/MCAtom.h +++ b/include/llvm/MC/MCAtom.h @@ -16,6 +16,7 @@ #ifndef LLVM_MC_MCATOM_H #define LLVM_MC_MCATOM_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/DataTypes.h" #include <vector> @@ -28,9 +29,10 @@ class MCAtom; class MCTextAtom; class MCDataAtom; -/// MCAtom - Represents a contiguous range of either instructions (a TextAtom) +/// \brief Represents a contiguous range of either instructions (a TextAtom) /// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. class MCAtom { + virtual void anchor(); public: virtual ~MCAtom() {} @@ -138,7 +140,7 @@ public: const MCDecodedInst &back() const { return Insts.back(); } const MCDecodedInst &at(size_t n) const { return Insts.at(n); } - uint64_t size() const { return Insts.size(); } + size_t size() const { return Insts.size(); } /// @} /// \name Atom type specific split/truncate logic. @@ -172,6 +174,9 @@ public: /// Append a data entry, expanding the atom if necessary. void addData(const MCData &D); + /// Get a reference to the data in this atom. + ArrayRef<MCData> getData() const { return Data; } + /// \name Atom type specific split/truncate logic. /// @{ MCDataAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; @@ -184,7 +189,9 @@ private: friend class MCModule; // Private constructor - only callable by MCModule MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) - : MCAtom(DataAtom, P, Begin, End), Data(End - Begin) {} + : MCAtom(DataAtom, P, Begin, End) { + Data.reserve(End + 1 - Begin); + } }; } diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h index d1765e1..84ce934 100644 --- a/include/llvm/MC/MCCodeGenInfo.h +++ b/include/llvm/MC/MCCodeGenInfo.h @@ -42,6 +42,9 @@ namespace llvm { CodeModel::Model getCodeModel() const { return CMModel; } CodeGenOpt::Level getOptLevel() const { return OptLevel; } + + // Allow overriding OptLevel on a per-function basis. + void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } }; } // namespace llvm diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index c012ed0..c8b6626 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -258,9 +258,15 @@ namespace llvm { const MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, - SectionKind Kind, int Selection = 0, + SectionKind Kind, + StringRef COMDATSymName, + int Selection, const MCSectionCOFF *Assoc = 0); + const MCSectionCOFF *getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind); + const MCSectionCOFF *getCOFFSection(StringRef Section); /// @} @@ -406,7 +412,7 @@ namespace llvm { void Deallocate(void *Ptr) { } - // Unrecoverable error has occured. Display the best diagnostic we can + // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg); diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index e82b0c1..83f26ef 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -131,6 +131,8 @@ public: void *getDisInfoBlock() const { return DisInfo; } MCContext *getMCContext() const { return Ctx; } + const MCSubtargetInfo& getSubtargetInfo() const { return STI; } + // Marked mutable because we cache it inside the disassembler, rather than // having to pass it around as an argument through all the autogenerated code. mutable raw_ostream *CommentStream; diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 3ece262..65b920b 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -23,400 +23,445 @@ #include <vector> namespace llvm { - class MCContext; - class MCSection; - class MCStreamer; - class MCSymbol; - class SourceMgr; - class SMLoc; - - /// MCDwarfFile - Instances of this class represent the name of the dwarf - /// .file directive and its associated dwarf file number in the MC file, - /// and MCDwarfFile's are created and unique'd by the MCContext class where - /// the file number for each is its index into the vector of DwarfFiles (note - /// index 0 is not used and not a valid dwarf file number). - class MCDwarfFile { - // Name - the base name of the file without its directory path. - // The StringRef references memory allocated in the MCContext. - StringRef Name; - - // DirIndex - the index into the list of directory names for this file name. - unsigned DirIndex; - - private: // MCContext creates and uniques these. - friend class MCContext; - MCDwarfFile(StringRef name, unsigned dirIndex) +class MCAsmBackend; +class MCContext; +class MCSection; +class MCStreamer; +class MCSymbol; +class SourceMgr; +class SMLoc; + +/// MCDwarfFile - Instances of this class represent the name of the dwarf +/// .file directive and its associated dwarf file number in the MC file, +/// and MCDwarfFile's are created and unique'd by the MCContext class where +/// the file number for each is its index into the vector of DwarfFiles (note +/// index 0 is not used and not a valid dwarf file number). +class MCDwarfFile { + // Name - the base name of the file without its directory path. + // The StringRef references memory allocated in the MCContext. + StringRef Name; + + // DirIndex - the index into the list of directory names for this file name. + unsigned DirIndex; + +private: // MCContext creates and uniques these. + friend class MCContext; + MCDwarfFile(StringRef name, unsigned dirIndex) : Name(name), DirIndex(dirIndex) {} - MCDwarfFile(const MCDwarfFile&) LLVM_DELETED_FUNCTION; - void operator=(const MCDwarfFile&) LLVM_DELETED_FUNCTION; - public: - /// getName - Get the base name of this MCDwarfFile. - StringRef getName() const { return Name; } - - /// getDirIndex - Get the dirIndex of this MCDwarfFile. - unsigned getDirIndex() const { return DirIndex; } - - - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS) const; - - /// dump - Print the value to stderr. - void dump() const; - }; - - inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){ - DwarfFile.print(OS); - return OS; - } - - /// MCDwarfLoc - Instances of this class represent the information from a - /// dwarf .loc directive. - class MCDwarfLoc { - // FileNum - the file number. - unsigned FileNum; - // Line - the line number. - unsigned Line; - // Column - the column position. - unsigned Column; - // Flags (see #define's below) - unsigned Flags; - // Isa - unsigned Isa; - // Discriminator - unsigned Discriminator; + MCDwarfFile(const MCDwarfFile &) LLVM_DELETED_FUNCTION; + void operator=(const MCDwarfFile &) LLVM_DELETED_FUNCTION; + +public: + /// getName - Get the base name of this MCDwarfFile. + StringRef getName() const { return Name; } + + /// getDirIndex - Get the dirIndex of this MCDwarfFile. + unsigned getDirIndex() const { return DirIndex; } + + /// print - Print the value to the stream \p OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile) { + DwarfFile.print(OS); + return OS; +} + +/// MCDwarfLoc - Instances of this class represent the information from a +/// dwarf .loc directive. +class MCDwarfLoc { + // FileNum - the file number. + unsigned FileNum; + // Line - the line number. + unsigned Line; + // Column - the column position. + unsigned Column; + // Flags (see #define's below) + unsigned Flags; + // Isa + unsigned Isa; + // Discriminator + unsigned Discriminator; // Flag that indicates the initial value of the is_stmt_start flag. -#define DWARF2_LINE_DEFAULT_IS_STMT 1 +#define DWARF2_LINE_DEFAULT_IS_STMT 1 -#define DWARF2_FLAG_IS_STMT (1 << 0) -#define DWARF2_FLAG_BASIC_BLOCK (1 << 1) -#define DWARF2_FLAG_PROLOGUE_END (1 << 2) +#define DWARF2_FLAG_IS_STMT (1 << 0) +#define DWARF2_FLAG_BASIC_BLOCK (1 << 1) +#define DWARF2_FLAG_PROLOGUE_END (1 << 2) #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) - private: // MCContext manages these - friend class MCContext; - friend class MCLineEntry; - MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, - unsigned isa, unsigned discriminator) +private: // MCContext manages these + friend class MCContext; + friend class MCLineEntry; + MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, + unsigned isa, unsigned discriminator) : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), Discriminator(discriminator) {} - // Allow the default copy constructor and assignment operator to be used - // for an MCDwarfLoc object. + // Allow the default copy constructor and assignment operator to be used + // for an MCDwarfLoc object. - public: - /// getFileNum - Get the FileNum of this MCDwarfLoc. - unsigned getFileNum() const { return FileNum; } +public: + /// getFileNum - Get the FileNum of this MCDwarfLoc. + unsigned getFileNum() const { return FileNum; } - /// getLine - Get the Line of this MCDwarfLoc. - unsigned getLine() const { return Line; } + /// getLine - Get the Line of this MCDwarfLoc. + unsigned getLine() const { return Line; } - /// getColumn - Get the Column of this MCDwarfLoc. - unsigned getColumn() const { return Column; } + /// getColumn - Get the Column of this MCDwarfLoc. + unsigned getColumn() const { return Column; } - /// getFlags - Get the Flags of this MCDwarfLoc. - unsigned getFlags() const { return Flags; } + /// getFlags - Get the Flags of this MCDwarfLoc. + unsigned getFlags() const { return Flags; } - /// getIsa - Get the Isa of this MCDwarfLoc. - unsigned getIsa() const { return Isa; } + /// getIsa - Get the Isa of this MCDwarfLoc. + unsigned getIsa() const { return Isa; } - /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. - unsigned getDiscriminator() const { return Discriminator; } + /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. + unsigned getDiscriminator() const { return Discriminator; } - /// setFileNum - Set the FileNum of this MCDwarfLoc. - void setFileNum(unsigned fileNum) { FileNum = fileNum; } + /// setFileNum - Set the FileNum of this MCDwarfLoc. + void setFileNum(unsigned fileNum) { FileNum = fileNum; } - /// setLine - Set the Line of this MCDwarfLoc. - void setLine(unsigned line) { Line = line; } + /// setLine - Set the Line of this MCDwarfLoc. + void setLine(unsigned line) { Line = line; } - /// setColumn - Set the Column of this MCDwarfLoc. - void setColumn(unsigned column) { Column = column; } + /// setColumn - Set the Column of this MCDwarfLoc. + void setColumn(unsigned column) { Column = column; } - /// setFlags - Set the Flags of this MCDwarfLoc. - void setFlags(unsigned flags) { Flags = flags; } + /// setFlags - Set the Flags of this MCDwarfLoc. + void setFlags(unsigned flags) { Flags = flags; } - /// setIsa - Set the Isa of this MCDwarfLoc. - void setIsa(unsigned isa) { Isa = isa; } + /// setIsa - Set the Isa of this MCDwarfLoc. + void setIsa(unsigned isa) { Isa = isa; } - /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. - void setDiscriminator(unsigned discriminator) { - Discriminator = discriminator; - } - }; + /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. + void setDiscriminator(unsigned discriminator) { + Discriminator = discriminator; + } +}; + +/// MCLineEntry - Instances of this class represent the line information for +/// the dwarf line table entries. Which is created after a machine +/// instruction is assembled and uses an address from a temporary label +/// created at the current address in the current section and the info from +/// the last .loc directive seen as stored in the context. +class MCLineEntry : public MCDwarfLoc { + MCSymbol *Label; + +private: + // Allow the default copy constructor and assignment operator to be used + // for an MCLineEntry object. + +public: + // Constructor to create an MCLineEntry given a symbol and the dwarf loc. + MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) + : MCDwarfLoc(loc), Label(label) {} + + MCSymbol *getLabel() const { return Label; } + + // This is called when an instruction is assembled into the specified + // section and if there is information from the last .loc directive that + // has yet to have a line entry made for it is made. + static void Make(MCStreamer *MCOS, const MCSection *Section); +}; + +/// MCLineSection - Instances of this class represent the line information +/// for a section where machine instructions have been assembled after seeing +/// .loc directives. This is the information used to build the dwarf line +/// table for a section. +class MCLineSection { + +private: + MCLineSection(const MCLineSection &) LLVM_DELETED_FUNCTION; + void operator=(const MCLineSection &) LLVM_DELETED_FUNCTION; + +public: + // Constructor to create an MCLineSection with an empty MCLineEntries + // vector. + MCLineSection() {} + + // addLineEntry - adds an entry to this MCLineSection's line entries + void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { + MCLineDivisions[CUID].push_back(LineEntry); + } - /// MCLineEntry - Instances of this class represent the line information for - /// the dwarf line table entries. Which is created after a machine - /// instruction is assembled and uses an address from a temporary label - /// created at the current address in the current section and the info from - /// the last .loc directive seen as stored in the context. - class MCLineEntry : public MCDwarfLoc { - MCSymbol *Label; - - private: - // Allow the default copy constructor and assignment operator to be used - // for an MCLineEntry object. - - public: - // Constructor to create an MCLineEntry given a symbol and the dwarf loc. - MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), - Label(label) {} - - MCSymbol *getLabel() const { return Label; } - - // This is called when an instruction is assembled into the specified - // section and if there is information from the last .loc directive that - // has yet to have a line entry made for it is made. - static void Make(MCStreamer *MCOS, const MCSection *Section); - }; + typedef std::vector<MCLineEntry> MCLineEntryCollection; + typedef MCLineEntryCollection::iterator iterator; + typedef MCLineEntryCollection::const_iterator const_iterator; + typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap; + +private: + // A collection of MCLineEntry for each Compile Unit ID. + MCLineDivisionMap MCLineDivisions; - /// MCLineSection - Instances of this class represent the line information - /// for a section where machine instructions have been assembled after seeing - /// .loc directives. This is the information used to build the dwarf line - /// table for a section. - class MCLineSection { - - private: - MCLineSection(const MCLineSection&) LLVM_DELETED_FUNCTION; - void operator=(const MCLineSection&) LLVM_DELETED_FUNCTION; - - public: - // Constructor to create an MCLineSection with an empty MCLineEntries - // vector. - MCLineSection() {} - - // addLineEntry - adds an entry to this MCLineSection's line entries - void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { - MCLineDivisions[CUID].push_back(LineEntry); - } - - typedef std::vector<MCLineEntry> MCLineEntryCollection; - typedef MCLineEntryCollection::iterator iterator; - typedef MCLineEntryCollection::const_iterator const_iterator; - typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap; - - private: - // A collection of MCLineEntry for each Compile Unit ID. - MCLineDivisionMap MCLineDivisions; - - public: - // Returns whether MCLineSection contains entries for a given Compile - // Unit ID. - bool containEntriesForID(unsigned CUID) const { - return MCLineDivisions.count(CUID); - } - // Returns the collection of MCLineEntry for a given Compile Unit ID. - const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { - MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); - assert(CIter != MCLineDivisions.end()); - return CIter->second; - } +public: + // Returns whether MCLineSection contains entries for a given Compile + // Unit ID. + bool containEntriesForID(unsigned CUID) const { + return MCLineDivisions.count(CUID); + } + // Returns the collection of MCLineEntry for a given Compile Unit ID. + const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { + MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); + assert(CIter != MCLineDivisions.end()); + return CIter->second; + } +}; + +class MCDwarfFileTable { +public: + // + // This emits the Dwarf file and the line tables for all Compile Units. + // + static const MCSymbol *Emit(MCStreamer *MCOS); + // + // This emits the Dwarf file and the line tables for a given Compile Unit. + // + static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); +}; + +class MCDwarfLineAddr { +public: + /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. + static void Encode(MCContext &Context, int64_t LineDelta, uint64_t AddrDelta, + raw_ostream &OS); + + /// Utility function to emit the encoding to a streamer. + static void Emit(MCStreamer *MCOS, int64_t LineDelta, uint64_t AddrDelta); +}; + +class MCGenDwarfInfo { +public: + // + // When generating dwarf for assembly source files this emits the Dwarf + // sections. + // + static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); +}; + +// When generating dwarf for assembly source files this is the info that is +// needed to be gathered for each symbol that will have a dwarf label. +class MCGenDwarfLabelEntry { +private: + // Name of the symbol without a leading underbar, if any. + StringRef Name; + // The dwarf file number this symbol is in. + unsigned FileNumber; + // The line number this symbol is at. + unsigned LineNumber; + // The low_pc for the dwarf label is taken from this symbol. + MCSymbol *Label; + +public: + MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, + MCSymbol *label) + : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), + Label(label) {} + + StringRef getName() const { return Name; } + unsigned getFileNumber() const { return FileNumber; } + unsigned getLineNumber() const { return LineNumber; } + MCSymbol *getLabel() const { return Label; } + + // This is called when label is created when we are generating dwarf for + // assembly source files. + static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, + SMLoc &Loc); +}; + +class MCCFIInstruction { +public: + enum OpType { + OpSameValue, + OpRememberState, + OpRestoreState, + OpOffset, + OpDefCfaRegister, + OpDefCfaOffset, + OpDefCfa, + OpRelOffset, + OpAdjustCfaOffset, + OpEscape, + OpRestore, + OpUndefined, + OpRegister, + OpWindowSave }; - class MCDwarfFileTable { - public: - // - // This emits the Dwarf file and the line tables for all Compile Units. - // - static const MCSymbol *Emit(MCStreamer *MCOS); - // - // This emits the Dwarf file and the line tables for a given Compile Unit. - // - static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); +private: + OpType Operation; + MCSymbol *Label; + unsigned Register; + union { + int Offset; + unsigned Register2; }; + std::vector<char> Values; - class MCDwarfLineAddr { - public: - /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. - static void Encode(MCContext &Context, int64_t LineDelta, - uint64_t AddrDelta, raw_ostream &OS); + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) + : Operation(Op), Label(L), Register(R), Offset(O), + Values(V.begin(), V.end()) { + assert(Op != OpRegister); + } - /// Utility function to emit the encoding to a streamer. - static void Emit(MCStreamer *MCOS, - int64_t LineDelta,uint64_t AddrDelta); - }; + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) + : Operation(Op), Label(L), Register(R1), Register2(R2) { + assert(Op == OpRegister); + } - class MCGenDwarfInfo { - public: - // - // When generating dwarf for assembly source files this emits the Dwarf - // sections. - // - static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); - }; +public: + /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from + /// Register and add Offset to it. + static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); + } - // When generating dwarf for assembly source files this is the info that is - // needed to be gathered for each symbol that will have a dwarf label. - class MCGenDwarfLabelEntry { - private: - // Name of the symbol without a leading underbar, if any. - StringRef Name; - // The dwarf file number this symbol is in. - unsigned FileNumber; - // The line number this symbol is at. - unsigned LineNumber; - // The low_pc for the dwarf label is taken from this symbol. - MCSymbol *Label; - - public: - MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, - unsigned lineNumber, MCSymbol *label) : - Name(name), FileNumber(fileNumber), LineNumber(lineNumber), Label(label){} - - StringRef getName() const { return Name; } - unsigned getFileNumber() const { return FileNumber; } - unsigned getLineNumber() const { return LineNumber; } - MCSymbol *getLabel() const { return Label; } - - // This is called when label is created when we are generating dwarf for - // assembly source files. - static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, - SMLoc &Loc); - }; + /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now + /// on Register will be used instead of the old one. Offset remains the same. + static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); + } - class MCCFIInstruction { - public: - enum OpType { OpSameValue, OpRememberState, OpRestoreState, OpOffset, - OpDefCfaRegister, OpDefCfaOffset, OpDefCfa, OpRelOffset, - OpAdjustCfaOffset, OpEscape, OpRestore, OpUndefined, - OpRegister }; - private: - OpType Operation; - MCSymbol *Label; - unsigned Register; - union { - int Offset; - unsigned Register2; - }; - std::vector<char> Values; - - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) : - Operation(Op), Label(L), Register(R), Offset(O), - Values(V.begin(), V.end()) { - assert(Op != OpRegister); - } - - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) : - Operation(Op), Label(L), Register(R1), Register2(R2) { - assert(Op == OpRegister); - } - - public: - static MCCFIInstruction - createOffset(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpOffset, L, Register, Offset, ""); - } - - static MCCFIInstruction - createDefCfaRegister(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); - } - - static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { - return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); - } - - static MCCFIInstruction - createDefCfa(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); - } - - static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpUndefined, L, Register, 0, ""); - } - - static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpRestore, L, Register, 0, ""); - } - - static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpSameValue, L, Register, 0, ""); - } - - static MCCFIInstruction createRestoreState(MCSymbol *L) { - return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); - } - - static MCCFIInstruction createRememberState(MCSymbol *L) { - return MCCFIInstruction(OpRememberState, L, 0, 0, ""); - } - - static MCCFIInstruction - createRelOffset(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); - } - - static MCCFIInstruction - createAdjustCfaOffset(MCSymbol *L, int Adjustment) { - return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); - } - - static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { - return MCCFIInstruction(OpEscape, L, 0, 0, Vals); - } - - static MCCFIInstruction - createRegister(MCSymbol *L, unsigned Register1, unsigned Register2) { - return MCCFIInstruction(OpRegister, L, Register1, Register2); - } - - OpType getOperation() const { return Operation; } - MCSymbol *getLabel() const { return Label; } - - unsigned getRegister() const { - assert(Operation == OpDefCfa || Operation == OpOffset || - Operation == OpRestore || Operation == OpUndefined || - Operation == OpSameValue || Operation == OpDefCfaRegister || - Operation == OpRelOffset || Operation == OpRegister); - return Register; - } - - unsigned getRegister2() const { - assert(Operation == OpRegister); - return Register2; - } - - int getOffset() const { - assert(Operation == OpDefCfa || Operation == OpOffset || - Operation == OpRelOffset || Operation == OpDefCfaOffset || - Operation == OpAdjustCfaOffset); - return Offset; - } - - const StringRef getValues() const { - assert(Operation == OpEscape); - return StringRef(&Values[0], Values.size()); - } - }; + /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register + /// remains the same, but offset is new. Note that it is the absolute offset + /// that will be added to a defined register to the compute CFA address. + static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { + return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); + } - struct MCDwarfFrameInfo { - MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), - Function(0), Instructions(), PersonalityEncoding(), - LsdaEncoding(0), CompactUnwindEncoding(0), - IsSignalFrame(false) {} - MCSymbol *Begin; - MCSymbol *End; - const MCSymbol *Personality; - const MCSymbol *Lsda; - const MCSymbol *Function; - std::vector<MCCFIInstruction> Instructions; - unsigned PersonalityEncoding; - unsigned LsdaEncoding; - uint32_t CompactUnwindEncoding; - bool IsSignalFrame; - }; + /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but + /// Offset is a relative value that is added/subtracted from the previous + /// offset. + static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { + return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); + } - class MCDwarfFrameEmitter { - public: - // - // This emits the frame info section. - // - static void Emit(MCStreamer &streamer, bool usingCFI, - bool isEH); - static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); - static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, - raw_ostream &OS); - }; + /// \brief .cfi_offset Previous value of Register is saved at offset Offset + /// from CFA. + static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpOffset, L, Register, Offset, ""); + } + + /// \brief .cfi_rel_offset Previous value of Register is saved at offset + /// Offset from the current CFA register. This is transformed to .cfi_offset + /// using the known displacement of the CFA register from the CFA. + static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); + } + + /// \brief .cfi_register Previous value of Register1 is saved in + /// register Register2. + static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, + unsigned Register2) { + return MCCFIInstruction(OpRegister, L, Register1, Register2); + } + + /// \brief .cfi_window_save SPARC register window is saved. + static MCCFIInstruction createWindowSave(MCSymbol *L) { + return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); + } + + /// \brief .cfi_restore says that the rule for Register is now the same as it + /// was at the beginning of the function, after all initial instructions added + /// by .cfi_startproc were executed. + static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpRestore, L, Register, 0, ""); + } + + /// \brief .cfi_undefined From now on the previous value of Register can't be + /// restored anymore. + static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpUndefined, L, Register, 0, ""); + } + + /// \brief .cfi_same_value Current value of Register is the same as in the + /// previous frame. I.e., no restoration is needed. + static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpSameValue, L, Register, 0, ""); + } + + /// \brief .cfi_remember_state Save all current rules for all registers. + static MCCFIInstruction createRememberState(MCSymbol *L) { + return MCCFIInstruction(OpRememberState, L, 0, 0, ""); + } + + /// \brief .cfi_restore_state Restore the previously saved state. + static MCCFIInstruction createRestoreState(MCSymbol *L) { + return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); + } + + /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind + /// info. + static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { + return MCCFIInstruction(OpEscape, L, 0, 0, Vals); + } + + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + + unsigned getRegister() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRestore || Operation == OpUndefined || + Operation == OpSameValue || Operation == OpDefCfaRegister || + Operation == OpRelOffset || Operation == OpRegister); + return Register; + } + + unsigned getRegister2() const { + assert(Operation == OpRegister); + return Register2; + } + + int getOffset() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRelOffset || Operation == OpDefCfaOffset || + Operation == OpAdjustCfaOffset); + return Offset; + } + + const StringRef getValues() const { + assert(Operation == OpEscape); + return StringRef(&Values[0], Values.size()); + } +}; + +struct MCDwarfFrameInfo { + MCDwarfFrameInfo() + : Begin(0), End(0), Personality(0), Lsda(0), Function(0), Instructions(), + PersonalityEncoding(), LsdaEncoding(0), CompactUnwindEncoding(0), + IsSignalFrame(false) {} + MCSymbol *Begin; + MCSymbol *End; + const MCSymbol *Personality; + const MCSymbol *Lsda; + const MCSymbol *Function; + std::vector<MCCFIInstruction> Instructions; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + uint32_t CompactUnwindEncoding; + bool IsSignalFrame; +}; + +class MCDwarfFrameEmitter { +public: + // + // This emits the frame info section. + // + static void Emit(MCStreamer &streamer, MCAsmBackend *MAB, + bool usingCFI, bool isEH); + static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); + static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, + raw_ostream &OS); +}; } // end namespace llvm #endif diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 7565c15..4e24dcf 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -28,20 +28,17 @@ class MCSymbolData; class raw_ostream; class MCELFStreamer : public MCObjectStreamer { -protected: - MCELFStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Kind, Context, TAB, OS, Emitter) {} - public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter) - : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter) {} + MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter), + SeenIdent(false) {} - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, MCAssembler *Assembler) - : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter, - Assembler) {} + MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, + MCAssembler *Assembler) + : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter, Assembler), + SeenIdent(false) {} virtual ~MCELFStreamer(); @@ -57,7 +54,7 @@ public: virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); @@ -81,16 +78,13 @@ public: virtual void EmitFileDirective(StringRef Filename); - virtual void EmitTCEntry(const MCSymbol &S); + virtual void EmitIdent(StringRef IdentString); virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned); - virtual void FinishImpl(); - /// @} + virtual void Flush(); - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_ELFStreamer || S->getKind() == SK_ARMELFStreamer; - } + virtual void FinishImpl(); private: virtual void EmitInstToFragment(const MCInst &Inst); @@ -102,6 +96,8 @@ private: void fixSymbolsInTLSFixups(const MCExpr *expr); + bool SeenIdent; + struct LocalCommon { MCSymbolData *SD; uint64_t Size; @@ -120,6 +116,11 @@ private: void SetSectionBss(); }; +MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter, + bool RelaxAll, bool NoExecStack, + bool IsThumb); + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h index 2225ea0..d0e1dac 100644 --- a/include/llvm/MC/MCELFSymbolFlags.h +++ b/include/llvm/MC/MCELFSymbolFlags.h @@ -27,7 +27,7 @@ namespace llvm { ELF_Other_Shift = 10 // Shift value for other flags. }; - enum SymbolFlags { + enum ELFSymbolFlags { ELF_STB_Local = (ELF::STB_LOCAL << ELF_STB_Shift), ELF_STB_Global = (ELF::STB_GLOBAL << ELF_STB_Shift), ELF_STB_Weak = (ELF::STB_WEAK << ELF_STB_Shift), diff --git a/include/llvm/MC/MCFunction.h b/include/llvm/MC/MCFunction.h index b85011e..22c9192 100644 --- a/include/llvm/MC/MCFunction.h +++ b/include/llvm/MC/MCFunction.h @@ -70,25 +70,33 @@ public: void addPredecessor(const MCBasicBlock *MCBB); bool isPredecessor(const MCBasicBlock *MCBB) const; + + /// \brief Split block, mirrorring NewAtom = Insts->split(..). + /// This moves all successors to \p SplitBB, and + /// adds a fallthrough to it. + /// \p SplitBB The result of splitting Insts, a basic block directly following + /// this basic block. + void splitBasicBlock(MCBasicBlock *SplitBB); /// @} }; /// \brief Represents a function in machine code, containing MCBasicBlocks. -/// MCFunctions are created using MCModule::createFunction. +/// MCFunctions are created by MCModule. class MCFunction { MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION; MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION; std::string Name; + MCModule *ParentModule; typedef std::vector<MCBasicBlock*> BasicBlockListTy; BasicBlockListTy Blocks; // MCModule owns the function. friend class MCModule; - MCFunction(StringRef Name); -public: + MCFunction(StringRef Name, MCModule *Parent); ~MCFunction(); +public: /// \brief Create an MCBasicBlock backed by Insts and add it to this function. /// \param Insts Sequence of straight-line code backing the basic block. /// \returns The newly created basic block. @@ -96,13 +104,21 @@ public: StringRef getName() const { return Name; } - /// \name Access to the function's basic blocks. No ordering is enforced. + /// \name Get the owning MC Module. + /// @{ + const MCModule *getParent() const { return ParentModule; } + MCModule *getParent() { return ParentModule; } + /// @} + + /// \name Access to the function's basic blocks. No ordering is enforced, + /// except that the first block is the entry block. /// @{ /// \brief Get the entry point basic block. const MCBasicBlock *getEntryBlock() const { return front(); } MCBasicBlock *getEntryBlock() { return front(); } - // NOTE: Dereferencing iterators gives pointers, so maybe a list is best here. + bool empty() const { return Blocks.empty(); } + typedef BasicBlockListTy::const_iterator const_iterator; typedef BasicBlockListTy:: iterator iterator; const_iterator begin() const { return Blocks.begin(); } @@ -114,6 +130,10 @@ public: MCBasicBlock* front() { return Blocks.front(); } const MCBasicBlock* back() const { return Blocks.back(); } MCBasicBlock* back() { return Blocks.back(); } + + /// \brief Find the basic block, if any, that starts at \p StartAddr. + const MCBasicBlock *find(uint64_t StartAddr) const; + MCBasicBlock *find(uint64_t StartAddr); /// @} }; diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index cb7225f..b4258be 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -41,7 +41,7 @@ protected: const MCRegisterInfo &MRI; /// The current set of available features. - unsigned AvailableFeatures; + uint64_t AvailableFeatures; /// True if we are printing marked up assembly. bool UseMarkup; @@ -77,8 +77,8 @@ public: /// printRegName - Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - unsigned getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + uint64_t getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } bool getUseMarkup() const { return UseMarkup; } void setUseMarkup(bool Value) { UseMarkup = Value; } diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 310f706..214b593 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -17,6 +17,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -145,6 +146,10 @@ public: const uint16_t *ImplicitUses; // Registers implicitly read by this instr const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands + uint64_t DeprecatedFeatureMask;// Feature bits that this is deprecated on, if any + // A complex method to determine is a certain is deprecated or not, and return + // the reason for deprecation. + bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &); /// \brief Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. @@ -158,6 +163,20 @@ public: return -1; } + /// \brief Returns true if a certain instruction is deprecated and if so + /// returns the reason in \p Info. + bool getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI, + std::string &Info) const { + if (ComplexDeprecationInfo) + return ComplexDeprecationInfo(MI, STI, Info); + if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) { + // FIXME: it would be nice to include the subtarget feature here. + Info = "deprecated"; + return true; + } + return false; + } + /// \brief Return the opcode number for this descriptor. unsigned getOpcode() const { return Opcode; diff --git a/include/llvm/MC/MCMachOSymbolFlags.h b/include/llvm/MC/MCMachOSymbolFlags.h index 696436d..71f01fa 100644 --- a/include/llvm/MC/MCMachOSymbolFlags.h +++ b/include/llvm/MC/MCMachOSymbolFlags.h @@ -19,9 +19,9 @@ // the correct relocation information. namespace llvm { - /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest - /// 16 bits of the implementation defined flags. - enum SymbolFlags { // See <mach-o/nlist.h>. + /// MachOSymbolFlags - We store the value for the 'desc' symbol field in the + /// lowest 16 bits of the implementation defined flags. + enum MachOSymbolFlags { // See <mach-o/nlist.h>. SF_DescFlagsMask = 0xFFFF, // Reference type flags. diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 3c9a588..3ba6e65 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -15,8 +15,8 @@ #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" -#include "llvm/Object/MachOFormat.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MachO.h" #include <vector> namespace llvm { @@ -98,7 +98,7 @@ class MachObjectWriter : public MCObjectWriter { /// @{ llvm::DenseMap<const MCSectionData*, - std::vector<object::macho::RelocationEntry> > Relocations; + std::vector<MachO::any_relocation_info> > Relocations; llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase; /// @} @@ -155,9 +155,8 @@ public: bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool isARM() const { - uint32_t CPUType = TargetObjectWriter->getCPUType() & - ~object::mach::CTFM_ArchMask; - return CPUType == object::mach::CTM_ARM; + uint32_t CPUType = TargetObjectWriter->getCPUType() & ~MachO::CPU_ARCH_MASK; + return CPUType == MachO::CPU_TYPE_ARM; } /// @} @@ -213,7 +212,7 @@ public: // these through in many cases. void addRelocation(const MCSectionData *SD, - object::macho::RelocationEntry &MRE) { + MachO::any_relocation_info &MRE) { Relocations[SD].push_back(MRE); } diff --git a/include/llvm/MC/MCModule.h b/include/llvm/MC/MCModule.h index 02f8ca0..63635c7 100644 --- a/include/llvm/MC/MCModule.h +++ b/include/llvm/MC/MCModule.h @@ -23,6 +23,7 @@ namespace llvm { class MCAtom; +class MCBasicBlock; class MCDataAtom; class MCFunction; class MCObjectDisassembler; @@ -42,7 +43,9 @@ class MCModule { typedef std::vector<MCAtom*> AtomListTy; AtomListTy Atoms; + // For access to map/remap. friend class MCAtom; + /// \brief Remap \p Atom to the given range, and update its Begin/End fields. /// \param Atom An atom belonging to this module. /// An atom should always use this method to update its bounds, because this @@ -53,20 +56,38 @@ class MCModule { void map(MCAtom *NewAtom); /// @} + /// \name Basic block tracking + /// @{ + typedef std::vector<MCBasicBlock*> BBsByAtomTy; + BBsByAtomTy BBsByAtom; + + // For access to basic block > atom tracking. + friend class MCBasicBlock; + friend class MCTextAtom; + + /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom. + /// This is used to update succs/preds when \p Atom is split. + void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom); + void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA); + /// @} + /// \name Function tracking /// @{ typedef std::vector<MCFunction*> FunctionListTy; FunctionListTy Functions; /// @} + /// The address of the entrypoint function. + uint64_t Entrypoint; + MCModule (const MCModule &) LLVM_DELETED_FUNCTION; MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION; // MCObjectDisassembler creates MCModules. friend class MCObjectDisassembler; - MCModule() : Atoms() { } public: + MCModule() : Entrypoint(0) { } ~MCModule(); /// \name Create a new MCAtom covering the specified offset range. @@ -79,6 +100,8 @@ public: /// @{ const MCAtom *findAtomContaining(uint64_t Addr) const; MCAtom *findAtomContaining(uint64_t Addr); + const MCAtom *findFirstAtomAfter(uint64_t Addr) const; + MCAtom *findFirstAtomAfter(uint64_t Addr); typedef AtomListTy::const_iterator const_atom_iterator; typedef AtomListTy:: iterator atom_iterator; @@ -88,8 +111,8 @@ public: atom_iterator atom_end() { return Atoms.end(); } /// @} - /// \name Create a new MCFunction. - MCFunction *createFunction(const StringRef &Name); + /// \brief Create a new MCFunction. + MCFunction *createFunction(StringRef Name); /// \name Access to the owned function list. /// @{ @@ -100,6 +123,9 @@ public: const_func_iterator func_end() const { return Functions.end(); } func_iterator func_end() { return Functions.end(); } /// @} + + /// \brief Get the address of the entrypoint function, or 0 if there is none. + uint64_t getEntrypoint() const { return Entrypoint; } }; } diff --git a/include/llvm/MC/MCModuleYAML.h b/include/llvm/MC/MCModuleYAML.h new file mode 100644 index 0000000..281e3d8 --- /dev/null +++ b/include/llvm/MC/MCModuleYAML.h @@ -0,0 +1,41 @@ +//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file declares classes for handling the YAML representation +/// of MCModule. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMODULEYAML_H +#define LLVM_MC_MCMODULEYAML_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCModule.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class MCInstrInfo; +class MCRegisterInfo; + +/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS. +/// \returns The empty string on success, an error message on failure. +StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +/// \brief Creates a new module and returns it in \p MCM. +/// \returns The empty string on success, an error message on failure. +StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h index 749a54e..0d87d33 100644 --- a/include/llvm/MC/MCObjectDisassembler.h +++ b/include/llvm/MC/MCObjectDisassembler.h @@ -15,10 +15,18 @@ #ifndef LLVM_MC_MCOBJECTDISASSEMBLER_H #define LLVM_MC_MCOBJECTDISASSEMBLER_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryObject.h" +#include <vector> + namespace llvm { namespace object { class ObjectFile; + class MachOObjectFile; } class MCBasicBlock; @@ -26,6 +34,7 @@ class MCDisassembler; class MCFunction; class MCInstrAnalysis; class MCModule; +class MCObjectSymbolizer; /// \brief Disassemble an ObjectFile to an MCModule and MCFunctions. /// This class builds on MCDisassembler to disassemble whole sections, creating @@ -33,14 +42,11 @@ class MCModule; /// It can also be used to create a control flow graph consisting of MCFunctions /// and MCBasicBlocks. class MCObjectDisassembler { - const object::ObjectFile &Obj; - const MCDisassembler &Dis; - const MCInstrAnalysis &MIA; - public: MCObjectDisassembler(const object::ObjectFile &Obj, const MCDisassembler &Dis, const MCInstrAnalysis &MIA); + virtual ~MCObjectDisassembler() {} /// \brief Build an MCModule, creating atoms and optionally functions. /// \param withCFG Also build a CFG by adding MCFunctions to the Module. @@ -50,6 +56,72 @@ public: /// block atoms, which then each back an MCBasicBlock. MCModule *buildModule(bool withCFG = false); + MCModule *buildEmptyModule(); + + typedef std::vector<uint64_t> AddressSetTy; + /// \name Create a new MCFunction. + MCFunction *createFunction(MCModule *Module, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets); + + /// \brief Set the region on which to fallback if disassembly was requested + /// somewhere not accessible in the object file. + /// This is used for dynamic disassembly (see RawMemoryObject). + void setFallbackRegion(OwningPtr<MemoryObject> &Region) { + FallbackRegion.reset(Region.take()); + } + + /// \brief Set the symbolizer to use to get information on external functions. + /// Note that this isn't used to do instruction-level symbolization (that is, + /// plugged into MCDisassembler), but to symbolize function call targets. + void setSymbolizer(MCObjectSymbolizer *ObjectSymbolizer) { + MOS = ObjectSymbolizer; + } + + /// \brief Get the effective address of the entrypoint, or 0 if there is none. + virtual uint64_t getEntrypoint(); + + /// \name Get the addresses of static constructors/destructors in the object. + /// The caller is expected to know how to interpret the addresses; + /// for example, Mach-O init functions expect 5 arguments, not for ELF. + /// The addresses are original object file load addresses, not effective. + /// @{ + virtual ArrayRef<uint64_t> getStaticInitFunctions(); + virtual ArrayRef<uint64_t> getStaticExitFunctions(); + /// @} + + /// \name Translation between effective and objectfile load address. + /// @{ + /// \brief Compute the effective load address, from an objectfile virtual + /// address. This is implemented in a format-specific way, to take into + /// account things like PIE/ASLR when doing dynamic disassembly. + /// For example, on Mach-O this would be done by adding the VM addr slide, + /// on glibc ELF by keeping a map between segment load addresses, filled + /// using dl_iterate_phdr, etc.. + /// In most static situations and in the default impl., this returns \p Addr. + virtual uint64_t getEffectiveLoadAddr(uint64_t Addr); + + /// \brief Compute the original load address, as specified in the objectfile. + /// This is the inverse of getEffectiveLoadAddr. + virtual uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr); + /// @} + +protected: + const object::ObjectFile &Obj; + const MCDisassembler &Dis; + const MCInstrAnalysis &MIA; + MCObjectSymbolizer *MOS; + + /// \brief The fallback memory region, outside the object file. + OwningPtr<MemoryObject> FallbackRegion; + + /// \brief Return a memory region suitable for reading starting at \p Addr. + /// In most cases, this returns a StringRefMemoryObject backed by the + /// containing section. When no section was found, this returns the + /// FallbackRegion, if it is suitable. + /// If it is not, or if there is no fallback region, this returns 0. + MemoryObject *getRegionFor(uint64_t Addr); + private: /// \brief Fill \p Module by creating an atom for each section. /// This could be made much smarter, using information like symbols, but also @@ -62,6 +134,40 @@ private: /// When the CFG is built, contiguous instructions that were previously in a /// single MCTextAtom will be split in multiple basic block atoms. void buildCFG(MCModule *Module); + + MCBasicBlock *getBBAt(MCModule *Module, MCFunction *MCFN, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets); +}; + +class MCMachOObjectDisassembler : public MCObjectDisassembler { + const object::MachOObjectFile &MOOF; + + uint64_t VMAddrSlide; + uint64_t HeaderLoadAddress; + + // __DATA;__mod_init_func support. + llvm::StringRef ModInitContents; + // __DATA;__mod_exit_func support. + llvm::StringRef ModExitContents; + +public: + /// \brief Construct a Mach-O specific object disassembler. + /// \param VMAddrSlide The virtual address slide applied by dyld. + /// \param HeaderLoadAddress The load address of the mach_header for this + /// object. + MCMachOObjectDisassembler(const object::MachOObjectFile &MOOF, + const MCDisassembler &Dis, + const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, + uint64_t HeaderLoadAddress); + +protected: + uint64_t getEffectiveLoadAddr(uint64_t Addr) LLVM_OVERRIDE; + uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) LLVM_OVERRIDE; + uint64_t getEntrypoint() LLVM_OVERRIDE; + + ArrayRef<uint64_t> getStaticInitFunctions() LLVM_OVERRIDE; + ArrayRef<uint64_t> getStaticExitFunctions() LLVM_OVERRIDE; }; } diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index a5853b6..c48dcb0 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -125,6 +125,10 @@ protected: const MCSection *DwarfStrOffDWOSection; const MCSection *DwarfAddrSection; + /// Sections for newer gnu pubnames and pubtypes. + const MCSection *DwarfGnuPubNamesSection; + const MCSection *DwarfGnuPubTypesSection; + // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. const MCSection *TLSExtraDataSection; @@ -138,6 +142,8 @@ protected: /// ELF and MachO only. const MCSection *TLSBSSSection; // Defaults to ".tbss". + /// StackMap section. + const MCSection *StackMapSection; /// EHFrameSection - EH frame section. It is initialized on demand so it /// can be overwritten (with uniquing). @@ -223,6 +229,12 @@ public: const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} + const MCSection *getDwarfGnuPubNamesSection() const { + return DwarfGnuPubNamesSection; + } + const MCSection *getDwarfGnuPubTypesSection() const { + return DwarfGnuPubTypesSection; + } const MCSection *getDwarfDebugInlineSection() const { return DwarfDebugInlineSection; } @@ -275,6 +287,8 @@ public: const MCSection *getTLSDataSection() const { return TLSDataSection; } const MCSection *getTLSBSSSection() const { return TLSBSSSection; } + const MCSection *getStackMapSection() const { return StackMapSection; } + /// ELF specific sections. /// const MCSection *getDataRelSection() const { return DataRelSection; } diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 0affeee..5667544 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -40,10 +40,11 @@ class MCObjectStreamer : public MCStreamer { virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame); protected: - MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter); - MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, + MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &_OS, + MCCodeEmitter *_Emitter); + MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, MCAssembler *_Assembler); ~MCObjectStreamer(); @@ -116,12 +117,6 @@ public: virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); virtual void EmitZeros(uint64_t NumBytes); virtual void FinishImpl(); - - /// @} - - static bool classof(const MCStreamer *S) { - return S->getKind() >= SK_ELFStreamer && S->getKind() <= SK_WinCOFFStreamer; - } }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h index 555cf51..64b932e 100644 --- a/include/llvm/MC/MCObjectSymbolizer.h +++ b/include/llvm/MC/MCObjectSymbolizer.h @@ -32,22 +32,14 @@ class MCObjectSymbolizer : public MCSymbolizer { protected: const object::ObjectFile *Obj; - typedef DenseMap<uint64_t, object::RelocationRef> AddrToRelocMap; - typedef std::vector<object::SectionRef> SortedSectionList; - SortedSectionList SortedSections; - // Map a load address to the first relocation that applies there. As far as I // know, if there are several relocations at the exact same address, they are // related and the others can be determined from the first that was found in // the relocation table. For instance, on x86-64 mach-o, a SUBTRACTOR // relocation (referencing the minuend symbol) is followed by an UNSIGNED // relocation (referencing the subtrahend symbol). - AddrToRelocMap AddrToReloc; - - // Helpers around SortedSections. - SortedSectionList::const_iterator findSectionContaining(uint64_t Addr) const; - void insertSection(object::SectionRef Section); - + const object::RelocationRef *findRelocationAt(uint64_t Addr); + const object::SectionRef *findSectionContaining(uint64_t Addr); MCObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, const object::ObjectFile *Obj); @@ -56,18 +48,32 @@ public: /// \name Overridden MCSymbolizer methods: /// @{ bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, - int64_t Value, - uint64_t Address, bool IsBranch, - uint64_t Offset, uint64_t InstSize); + int64_t Value, uint64_t Address, + bool IsBranch, uint64_t Offset, + uint64_t InstSize); void tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value, uint64_t Address); /// @} + /// \brief Look for an external function symbol at \p Addr. + /// (References through the ELF PLT, Mach-O stubs, and similar). + /// \returns An MCExpr representing the external symbol, or 0 if not found. + virtual StringRef findExternalFunctionAt(uint64_t Addr); + /// \brief Create an object symbolizer for \p Obj. static MCObjectSymbolizer * createObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, const object::ObjectFile *Obj); + +private: + typedef DenseMap<uint64_t, object::RelocationRef> AddrToRelocMap; + typedef std::vector<object::SectionRef> SortedSectionList; + SortedSectionList SortedSections; + AddrToRelocMap AddrToReloc; + + void buildSectionList(); + void buildRelocationByAddrMap(); }; } diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 0dab314..1b3ab57 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -63,6 +63,7 @@ private: AsmToken LexSingleQuote(); AsmToken LexQuote(); AsmToken LexFloatLiteral(); + AsmToken LexHexFloatLiteral(bool NoIntDigits); }; } // end namespace llvm diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 673cdf6..6881e1d 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -124,7 +124,7 @@ struct MCSchedClassDesc { /// microarchitecture to the scheduler in the form of properties. It also /// optionally refers to scheduler resource tables and itinerary /// tables. Scheduler resource tables model the latency and cost for each -/// instruction type. Itinerary tables are an independant mechanism that +/// instruction type. Itinerary tables are an independent mechanism that /// provides a detailed reservation table describing each cycle of instruction /// execution. Subtargets may define any or all of the above categories of data /// depending on the type of CPU and selected scheduler. @@ -174,6 +174,8 @@ public: unsigned MispredictPenalty; static const unsigned DefaultMispredictPenalty = 10; + bool CompleteModel; + private: unsigned ProcID; const MCProcResourceDesc *ProcResourceTable; @@ -194,6 +196,7 @@ public: LoadLatency(DefaultLoadLatency), HighLatency(DefaultHighLatency), MispredictPenalty(DefaultMispredictPenalty), + CompleteModel(true), ProcID(0), ProcResourceTable(0), SchedClassTable(0), NumProcResourceKinds(0), NumSchedClasses(0), InstrItineraries(0) { @@ -203,19 +206,23 @@ public: // Table-gen driven ctor. MCSchedModel(unsigned iw, int mbs, unsigned ll, unsigned hl, - unsigned mp, unsigned pi, const MCProcResourceDesc *pr, + unsigned mp, bool cm, unsigned pi, const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, const InstrItinerary *ii): IssueWidth(iw), MicroOpBufferSize(mbs), LoadLatency(ll), HighLatency(hl), - MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), - SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc), - InstrItineraries(ii) {} + MispredictPenalty(mp), CompleteModel(cm), ProcID(pi), + ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), + NumSchedClasses(nsc), InstrItineraries(ii) {} unsigned getProcessorID() const { return ProcID; } /// Does this machine model include instruction-level scheduling. bool hasInstrSchedModel() const { return SchedClassTable; } + /// Return true if this machine model data for all instructions with a + /// scheduling class (itinerary class or SchedRW list). + bool isComplete() const { return CompleteModel; } + unsigned getNumProcResourceKinds() const { return NumProcResourceKinds; } diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 754e829..45c84ae 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -19,6 +19,7 @@ #include "llvm/Support/COFF.h" namespace llvm { +class MCSymbol; /// MCSectionCOFF - This represents a section on Windows class MCSectionCOFF : public MCSection { @@ -32,6 +33,11 @@ namespace llvm { /// drawn from the enums below. mutable unsigned Characteristics; + /// The COMDAT symbol of this section. Only valid if this is a COMDAT + /// section. Two COMDAT sections are merged if they have the same + /// COMDAT symbol. + const MCSymbol *COMDATSymbol; + /// Selection - This is the Selection field for the section symbol, if /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 mutable int Selection; @@ -44,9 +50,11 @@ namespace llvm { private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - int Selection, const MCSectionCOFF *Assoc, SectionKind K) - : MCSection(SV_COFF, K), SectionName(Section), - Characteristics(Characteristics), Selection(Selection), Assoc(Assoc) { + const MCSymbol *COMDATSymbol, int Selection, + const MCSectionCOFF *Assoc, SectionKind K) + : MCSection(SV_COFF, K), SectionName(Section), + Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), + Selection(Selection), Assoc(Assoc) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); assert ((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index b68bd85..d7e88ea 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -41,7 +41,7 @@ public: /// These are the section type and attributes fields. A MachO section can /// have only one Type, but can have any of the attributes specified. - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // TypeAndAttributes bitmasks. SECTION_TYPE = 0x000000FFU, SECTION_ATTRIBUTES = 0xFFFFFF00U, diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 970c4ed..0b1fe6e 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -24,675 +24,716 @@ #include <string> namespace llvm { - class MCAsmBackend; - class MCCodeEmitter; - class MCContext; - class MCExpr; - class MCInst; - class MCInstPrinter; - class MCSection; - class MCSymbol; - class StringRef; - class Twine; - class raw_ostream; - class formatted_raw_ostream; - - typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; - - /// MCStreamer - Streaming machine code generation interface. This interface - /// is intended to provide a programatic interface that is very similar to the - /// level that an assembler .s file provides. It has callbacks to emit bytes, - /// handle directives, etc. The implementation of this interface retains - /// state to know what the current section is etc. - /// - /// There are multiple implementations of this interface: one for writing out - /// a .s file, and implementations that write out .o files of various formats. - /// - class MCStreamer { - public: - enum StreamerKind { - SK_AsmStreamer, - SK_NullStreamer, - SK_RecordStreamer, - - // MCObjectStreamer subclasses. - SK_ELFStreamer, - SK_ARMELFStreamer, - SK_MachOStreamer, - SK_PureStreamer, - SK_MipsELFStreamer, - SK_WinCOFFStreamer - }; - - private: - const StreamerKind Kind; - MCContext &Context; - - MCStreamer(const MCStreamer&) LLVM_DELETED_FUNCTION; - MCStreamer &operator=(const MCStreamer&) LLVM_DELETED_FUNCTION; - - bool EmitEHFrame; - bool EmitDebugFrame; - - std::vector<MCDwarfFrameInfo> FrameInfos; - MCDwarfFrameInfo *getCurrentFrameInfo(); - MCSymbol *EmitCFICommon(); - void EnsureValidFrame(); - - std::vector<MCWin64EHUnwindInfo *> W64UnwindInfos; - MCWin64EHUnwindInfo *CurrentW64UnwindInfo; - void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); - void EnsureValidW64UnwindInfo(); - - MCSymbol* LastSymbol; - - /// SectionStack - This is stack of current and previous section - /// values saved by PushSection. - SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; - - bool AutoInitSections; - - protected: - MCStreamer(StreamerKind Kind, MCContext &Ctx); - - const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, - const MCSymbol *B); - - const MCExpr *ForceExpAbs(const MCExpr* Expr); - - void RecordProcStart(MCDwarfFrameInfo &Frame); - virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); - void RecordProcEnd(MCDwarfFrameInfo &Frame); - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); - void EmitFrames(bool usingCFI); - - MCWin64EHUnwindInfo *getCurrentW64UnwindInfo(){return CurrentW64UnwindInfo;} - void EmitW64Tables(); - - public: - virtual ~MCStreamer(); - - StreamerKind getKind() const { return Kind; } - - /// State management - /// - virtual void reset(); - - MCContext &getContext() const { return Context; } - - unsigned getNumFrameInfos() { - return FrameInfos.size(); - } +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCExpr; +class MCInst; +class MCInstPrinter; +class MCSection; +class MCStreamer; +class MCSymbol; +class StringRef; +class Twine; +class raw_ostream; +class formatted_raw_ostream; + +typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; + +/// Target specific streamer interface. This is used so that targets can +/// implement support for target specific assembly directives. +/// +/// If target foo wants to use this, it should implement 3 classes: +/// * FooTargetStreamer : public MCTargetStreamer +/// * FooTargetAsmSreamer : public FooTargetStreamer +/// * FooTargetELFStreamer : public FooTargetStreamer +/// +/// FooTargetStreamer should have a pure virtual method for each directive. For +/// example, for a ".bar symbol_name" directive, it should have +/// virtual emitBar(const MCSymbol &Symbol) = 0; +/// +/// The FooTargetAsmSreamer and FooTargetELFStreamer classes implement the +/// method. The assembly streamer just prints ".bar symbol_name". The object +/// streamer does whatever is needed to implement .bar in the object file. +/// +/// In the assembly printer and parser the target streamer can be used by +/// calling getTargetStreamer and casting it to FooTargetStreamer: +/// +/// MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); +/// FooTargetStreamer &ATS = static_cast<FooTargetStreamer &>(TS); +/// +/// The base classes FooTargetAsmSreamer and FooTargetELFStreamer should *never* +/// be treated differently. Callers should always talk to a FooTargetStreamer. +class MCTargetStreamer { +protected: + MCStreamer *Streamer; + +public: + virtual ~MCTargetStreamer(); + void setStreamer(MCStreamer *S) { Streamer = S; } +}; + +// FIXME: declared here because it is used from +// lib/CodeGen/AsmPrinter/ARMException.cpp. +class ARMTargetStreamer : public MCTargetStreamer { + virtual void anchor(); +public: + virtual void emitFnStart() = 0; + virtual void emitFnEnd() = 0; + virtual void emitCantUnwind() = 0; + virtual void emitPersonality(const MCSymbol *Personality) = 0; + virtual void emitHandlerData() = 0; + virtual void emitSetFP(unsigned FpReg, unsigned SpReg, + int64_t Offset = 0) = 0; + virtual void emitPad(int64_t Offset) = 0; + virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, + bool isVector) = 0; + + virtual void switchVendor(StringRef Vendor) = 0; + virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0; + virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0; + virtual void emitFPU(unsigned FPU) = 0; + virtual void finishAttributeSection() = 0; +}; + +/// MCStreamer - Streaming machine code generation interface. This interface +/// is intended to provide a programatic interface that is very similar to the +/// level that an assembler .s file provides. It has callbacks to emit bytes, +/// handle directives, etc. The implementation of this interface retains +/// state to know what the current section is etc. +/// +/// There are multiple implementations of this interface: one for writing out +/// a .s file, and implementations that write out .o files of various formats. +/// +class MCStreamer { + MCContext &Context; + OwningPtr<MCTargetStreamer> TargetStreamer; + + MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; + MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; + + bool EmitEHFrame; + bool EmitDebugFrame; + + std::vector<MCDwarfFrameInfo> FrameInfos; + MCDwarfFrameInfo *getCurrentFrameInfo(); + MCSymbol *EmitCFICommon(); + void EnsureValidFrame(); + + std::vector<MCWin64EHUnwindInfo *> W64UnwindInfos; + MCWin64EHUnwindInfo *CurrentW64UnwindInfo; + void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); + void EnsureValidW64UnwindInfo(); + + MCSymbol *LastSymbol; + + // SymbolOrdering - Tracks an index to represent the order + // a symbol was emitted in. Zero means we did not emit that symbol. + DenseMap<const MCSymbol *, unsigned> SymbolOrdering; + + /// SectionStack - This is stack of current and previous section + /// values saved by PushSection. + SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; + + bool AutoInitSections; + +protected: + MCStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer); + + const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, + const MCSymbol *B); + + const MCExpr *ForceExpAbs(const MCExpr *Expr); + + void RecordProcStart(MCDwarfFrameInfo &Frame); + virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); + void RecordProcEnd(MCDwarfFrameInfo &Frame); + virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); + void EmitFrames(MCAsmBackend *MAB, bool usingCFI); + + MCWin64EHUnwindInfo *getCurrentW64UnwindInfo() { + return CurrentW64UnwindInfo; + } + void EmitW64Tables(); + + virtual void EmitRawTextImpl(StringRef String); + +public: + virtual ~MCStreamer(); + + /// State management + /// + virtual void reset(); - const MCDwarfFrameInfo &getFrameInfo(unsigned i) { - return FrameInfos[i]; - } + MCContext &getContext() const { return Context; } - ArrayRef<MCDwarfFrameInfo> getFrameInfos() { - return FrameInfos; - } + MCTargetStreamer &getTargetStreamer() { + assert(TargetStreamer); + return *TargetStreamer; + } - unsigned getNumW64UnwindInfos() { - return W64UnwindInfos.size(); - } + unsigned getNumFrameInfos() { return FrameInfos.size(); } - MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { - return *W64UnwindInfos[i]; - } + const MCDwarfFrameInfo &getFrameInfo(unsigned i) { return FrameInfos[i]; } - /// @name Assembly File Formatting. - /// @{ - - /// isVerboseAsm - Return true if this streamer supports verbose assembly - /// and if it is enabled. - virtual bool isVerboseAsm() const { return false; } - - /// hasRawTextSupport - Return true if this asm streamer supports emitting - /// unformatted text to the .s file with EmitRawText. - virtual bool hasRawTextSupport() const { return false; } - - /// AddComment - Add a comment that can be emitted to the generated .s - /// file if applicable as a QoI issue to make the output of the compiler - /// more readable. This only affects the MCAsmStreamer, and only when - /// verbose assembly output is enabled. - /// - /// If the comment includes embedded \n's, they will each get the comment - /// prefix as appropriate. The added comment should not end with a \n. - virtual void AddComment(const Twine &T) {} - - /// GetCommentOS - Return a raw_ostream that comments can be written to. - /// Unlike AddComment, you are required to terminate comments with \n if you - /// use this method. - virtual raw_ostream &GetCommentOS(); - - /// AddBlankLine - Emit a blank line to a .s file to pretty it up. - virtual void AddBlankLine() {} - - /// @} - - /// @name Symbol & Section Management - /// @{ - - /// getCurrentSection - Return the current section that the streamer is - /// emitting code to. - MCSectionSubPair getCurrentSection() const { - if (!SectionStack.empty()) - return SectionStack.back().first; - return MCSectionSubPair(); - } + ArrayRef<MCDwarfFrameInfo> getFrameInfos() const { return FrameInfos; } - /// getPreviousSection - Return the previous section that the streamer is - /// emitting code to. - MCSectionSubPair getPreviousSection() const { - if (!SectionStack.empty()) - return SectionStack.back().second; - return MCSectionSubPair(); - } + unsigned getNumW64UnwindInfos() { return W64UnwindInfos.size(); } - /// ChangeSection - Update streamer for a new active section. - /// - /// This is called by PopSection and SwitchSection, if the current - /// section changes. - virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; - - /// pushSection - Save the current and previous section on the - /// section stack. - void PushSection() { - SectionStack.push_back(std::make_pair(getCurrentSection(), - getPreviousSection())); - } + MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { + return *W64UnwindInfos[i]; + } - /// popSection - Restore the current and previous section from - /// the section stack. Calls ChangeSection as needed. - /// - /// Returns false if the stack was empty. - bool PopSection() { - if (SectionStack.size() <= 1) - return false; - MCSectionSubPair oldSection = SectionStack.pop_back_val().first; - MCSectionSubPair curSection = SectionStack.back().first; - - if (oldSection != curSection) - ChangeSection(curSection.first, curSection.second); - return true; - } + void generateCompactUnwindEncodings(MCAsmBackend *MAB); - bool SubSection(const MCExpr *Subsection) { - if (SectionStack.empty()) - return false; + /// @name Assembly File Formatting. + /// @{ - SwitchSection(SectionStack.back().first.first, Subsection); - return true; - } + /// isVerboseAsm - Return true if this streamer supports verbose assembly + /// and if it is enabled. + virtual bool isVerboseAsm() const { return false; } - /// SwitchSection - Set the current section where code is being emitted to - /// @p Section. This is required to update CurSection. - /// - /// This corresponds to assembler directives like .section, .text, etc. - void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) { - SectionStack.back().first = MCSectionSubPair(Section, Subsection); - ChangeSection(Section, Subsection); - } - } + /// hasRawTextSupport - Return true if this asm streamer supports emitting + /// unformatted text to the .s file with EmitRawText. + virtual bool hasRawTextSupport() const { return false; } - /// SwitchSectionNoChange - Set the current section where code is being - /// emitted to @p Section. This is required to update CurSection. This - /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section, - const MCExpr *Subsection = 0) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) - SectionStack.back().first = MCSectionSubPair(Section, Subsection); + /// AddComment - Add a comment that can be emitted to the generated .s + /// file if applicable as a QoI issue to make the output of the compiler + /// more readable. This only affects the MCAsmStreamer, and only when + /// verbose assembly output is enabled. + /// + /// If the comment includes embedded \n's, they will each get the comment + /// prefix as appropriate. The added comment should not end with a \n. + virtual void AddComment(const Twine &T) {} + + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS(); + + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. + virtual void AddBlankLine() {} + + /// @} + + /// @name Symbol & Section Management + /// @{ + + /// getCurrentSection - Return the current section that the streamer is + /// emitting code to. + MCSectionSubPair getCurrentSection() const { + if (!SectionStack.empty()) + return SectionStack.back().first; + return MCSectionSubPair(); + } + + /// getPreviousSection - Return the previous section that the streamer is + /// emitting code to. + MCSectionSubPair getPreviousSection() const { + if (!SectionStack.empty()) + return SectionStack.back().second; + return MCSectionSubPair(); + } + + /// GetSymbolOrder - Returns an index to represent the order + /// a symbol was emitted in. (zero if we did not emit that symbol) + unsigned GetSymbolOrder(const MCSymbol *Sym) const { + return SymbolOrdering.lookup(Sym); + } + + /// ChangeSection - Update streamer for a new active section. + /// + /// This is called by PopSection and SwitchSection, if the current + /// section changes. + virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; + + /// pushSection - Save the current and previous section on the + /// section stack. + void PushSection() { + SectionStack.push_back( + std::make_pair(getCurrentSection(), getPreviousSection())); + } + + /// popSection - Restore the current and previous section from + /// the section stack. Calls ChangeSection as needed. + /// + /// Returns false if the stack was empty. + bool PopSection() { + if (SectionStack.size() <= 1) + return false; + MCSectionSubPair oldSection = SectionStack.pop_back_val().first; + MCSectionSubPair curSection = SectionStack.back().first; + + if (oldSection != curSection) + ChangeSection(curSection.first, curSection.second); + return true; + } + + bool SubSection(const MCExpr *Subsection) { + if (SectionStack.empty()) + return false; + + SwitchSection(SectionStack.back().first.first, Subsection); + return true; + } + + /// SwitchSection - Set the current section where code is being emitted to + /// @p Section. This is required to update CurSection. + /// + /// This corresponds to assembler directives like .section, .text, etc. + void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) { + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + ChangeSection(Section, Subsection); } + } + + /// SwitchSectionNoChange - Set the current section where code is being + /// emitted to @p Section. This is required to update CurSection. This + /// version does not call ChangeSection. + void SwitchSectionNoChange(const MCSection *Section, + const MCExpr *Subsection = 0) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + } + + /// Initialize the streamer. + void InitStreamer() { + if (AutoInitSections) + InitSections(); + } + + /// Tell this MCStreamer to call InitSections upon initialization. + void setAutoInitSections(bool AutoInitSections) { + this->AutoInitSections = AutoInitSections; + } + + /// InitSections - Create the default sections and set the initial one. + virtual void InitSections() = 0; + + /// InitToTextSection - Create a text section and switch the streamer to it. + virtual void InitToTextSection() = 0; + + /// AssignSection - Sets the symbol's section. + /// + /// Each emitted symbol will be tracked in the ordering table, + /// so we can sort on them later. + void AssignSection(MCSymbol *Symbol, const MCSection *Section); - /// Initialize the streamer. - void InitStreamer() { - if (AutoInitSections) - InitSections(); - } + /// EmitLabel - Emit a label for @p Symbol into the current section. + /// + /// This corresponds to an assembler statement such as: + /// foo: + /// + /// @param Symbol - The symbol to emit. A given symbol should only be + /// emitted as a label once, and symbols emitted as a label should never be + /// used in an assignment. + virtual void EmitLabel(MCSymbol *Symbol); - /// Tell this MCStreamer to call InitSections upon initialization. - void setAutoInitSections(bool AutoInitSections) { - this->AutoInitSections = AutoInitSections; - } + virtual void EmitDebugLabel(MCSymbol *Symbol); - /// InitSections - Create the default sections and set the initial one. - virtual void InitSections() = 0; - - /// InitToTextSection - Create a text section and switch the streamer to it. - virtual void InitToTextSection() = 0; - - /// EmitLabel - Emit a label for @p Symbol into the current section. - /// - /// This corresponds to an assembler statement such as: - /// foo: - /// - /// @param Symbol - The symbol to emit. A given symbol should only be - /// emitted as a label once, and symbols emitted as a label should never be - /// used in an assignment. - virtual void EmitLabel(MCSymbol *Symbol); - - virtual void EmitDebugLabel(MCSymbol *Symbol); - - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol); - - /// EmitAssemblerFlag - Note in the output the specified @p Flag. - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; - - /// EmitLinkerOptions - Emit the given list @p Options of strings as linker - /// options into the output. - virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {} - - /// EmitDataRegion - Note in the output the specified region @p Kind. - virtual void EmitDataRegion(MCDataRegionType Kind) {} - - /// EmitThumbFunc - Note in the output that the specified @p Func is - /// a Thumb mode function (ARM target only). - virtual void EmitThumbFunc(MCSymbol *Func) = 0; - - /// getOrCreateSymbolData - Get symbol data for given symbol. - virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); - - /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. - /// - /// This corresponds to an assembler statement such as: - /// symbol = value - /// - /// The assignment generates no code, but has the side effect of binding the - /// value in the current context. For the assembly streamer, this prints the - /// binding into the .s file. - /// - /// @param Symbol - The symbol being assigned to. - /// @param Value - The value for the symbol. - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; - - /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. - /// - /// This corresponds to an assembler statement such as: - /// .weakref alias, symbol - /// - /// @param Alias - The alias that is being created. - /// @param Symbol - The symbol being aliased. - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; - - /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. - virtual void EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) = 0; - - /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. - /// - /// @param Symbol - The symbol to have its n_desc field set. - /// @param DescValue - The value to set into the n_desc field. - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; - - /// BeginCOFFSymbolDef - Start emitting COFF symbol definition - /// - /// @param Symbol - The symbol to have its External & Type fields set. - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; - - /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. - /// - /// @param StorageClass - The storage class the symbol should have. - virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; - - /// EmitCOFFSymbolType - Emit the type of the symbol. - /// - /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) - virtual void EmitCOFFSymbolType(int Type) = 0; - - /// EndCOFFSymbolDef - Marks the end of the symbol definition. - virtual void EndCOFFSymbolDef() = 0; - - /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. - /// - /// @param Symbol - Symbol the section relative realocation should point to. - virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - - /// EmitELFSize - Emit an ELF .size directive. - /// - /// This corresponds to an assembler statement such as: - /// .size symbol, expression - /// - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; - - /// EmitCommonSymbol - Emit a common symbol. - /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the symbol if - /// non-zero. This must be a power of 2. - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 0; - - /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. - /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the common symbol in bytes. - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 0; - - /// EmitZerofill - Emit the zerofill section and an optional symbol. - /// - /// @param Section - The zerofill section to create and or to put the symbol - /// @param Symbol - The zerofill symbol to emit, if non-NULL. - /// @param Size - The size of the zerofill symbol. - /// @param ByteAlignment - The alignment of the zerofill symbol if - /// non-zero. This must be a power of 2 on some targets. - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0,unsigned ByteAlignment = 0) = 0; - - /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. - /// - /// @param Section - The thread local common section. - /// @param Symbol - The thread local common symbol to emit. - /// @param Size - The size of the symbol. - /// @param ByteAlignment - The alignment of the thread local common symbol - /// if non-zero. This must be a power of 2 on some targets. - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) = 0; - - /// @} - /// @name Generating Data - /// @{ - - /// EmitBytes - Emit the bytes in \p Data into the output. - /// - /// This is used to implement assembler directives such as .byte, .ascii, - /// etc. - virtual void EmitBytes(StringRef Data) = 0; - - /// EmitValue - Emit the expression @p Value into the output as a native - /// integer of the given @p Size bytes. - /// - /// This is used to implement assembler directives such as .word, .quad, - /// etc. - /// - /// @param Value - The value to emit. - /// @param Size - The size of the integer (in bytes) to emit. This must - /// match a native machine width. - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) = 0; - - void EmitValue(const MCExpr *Value, unsigned Size); - - /// EmitIntValue - Special case of EmitValue that avoids the client having - /// to pass in a MCExpr for constant integers. - virtual void EmitIntValue(uint64_t Value, unsigned Size); - - /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO - /// this is done by producing - /// foo = value - /// .long foo - void EmitAbsValue(const MCExpr *Value, unsigned Size); - - virtual void EmitULEB128Value(const MCExpr *Value) = 0; - - virtual void EmitSLEB128Value(const MCExpr *Value) = 0; - - /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. - void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0); - - /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. - void EmitSLEB128IntValue(int64_t Value); - - /// EmitSymbolValue - Special case of EmitValue that avoids the client - /// having to pass in a MCExpr for MCSymbols. - void EmitSymbolValue(const MCSymbol *Sym, unsigned Size); - - /// EmitGPRel64Value - Emit the expression @p Value into the output as a - /// gprel64 (64-bit GP relative) value. - /// - /// This is used to implement assembler directives such as .gpdword on - /// targets that support them. - virtual void EmitGPRel64Value(const MCExpr *Value); - - /// EmitGPRel32Value - Emit the expression @p Value into the output as a - /// gprel32 (32-bit GP relative) value. - /// - /// This is used to implement assembler directives such as .gprel32 on - /// targets that support them. - virtual void EmitGPRel32Value(const MCExpr *Value); - - /// EmitFill - Emit NumBytes bytes worth of the value specified by - /// FillValue. This implements directives such as '.space'. - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); - - /// \brief Emit NumBytes worth of zeros. - /// This function properly handles data in virtual sections. - virtual void EmitZeros(uint64_t NumBytes); - - /// EmitValueToAlignment - Emit some number of copies of @p Value until - /// the byte alignment @p ByteAlignment is reached. - /// - /// If the number of bytes need to emit for the alignment is not a multiple - /// of @p ValueSize, then the contents of the emitted fill bytes is - /// undefined. - /// - /// This used to implement the .align assembler directive. - /// - /// @param ByteAlignment - The alignment to reach. This must be a power of - /// two on some targets. - /// @param Value - The value to use when filling bytes. - /// @param ValueSize - The size of the integer (in bytes) to emit for - /// @p Value. This must match a native machine width. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If - /// the alignment cannot be reached in this many bytes, no bytes are - /// emitted. - virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0) = 0; - - /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment - /// is reached. - /// - /// This used to align code where the alignment bytes may be executed. This - /// can emit different bytes for different sizes to optimize execution. - /// - /// @param ByteAlignment - The alignment to reach. This must be a power of - /// two on some targets. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If - /// the alignment cannot be reached in this many bytes, no bytes are - /// emitted. - virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0) = 0; - - /// EmitValueToOffset - Emit some number of copies of @p Value until the - /// byte offset @p Offset is reached. - /// - /// This is used to implement assembler directives such as .org. - /// - /// @param Offset - The offset to reach. This may be an expression, but the - /// expression must be associated with the current section. - /// @param Value - The value to use when filling bytes. - /// @return false on success, true if the offset was invalid. - virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0) = 0; - - /// @} - - /// EmitFileDirective - Switch to a new logical file. This is used to - /// implement the '.file "foo.c"' assembler directive. - virtual void EmitFileDirective(StringRef Filename) = 0; - - /// EmitDwarfFileDirective - Associate a filename with a specified logical - /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler - /// directive. - virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, unsigned CUID = 0); - - /// EmitDwarfLocDirective - This implements the DWARF2 - // '.loc fileno lineno ...' assembler directive. - virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, - unsigned Discriminator, - StringRef FileName); - - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) = 0; - - virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label) { - } + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, - int PointerSize); - - virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); - virtual void EmitCFISections(bool EH, bool Debug); - void EmitCFIStartProc(); - void EmitCFIEndProc(); - virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); - virtual void EmitCFIDefCfaOffset(int64_t Offset); - virtual void EmitCFIDefCfaRegister(int64_t Register); - virtual void EmitCFIOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFIRememberState(); - virtual void EmitCFIRestoreState(); - virtual void EmitCFISameValue(int64_t Register); - virtual void EmitCFIRestore(int64_t Register); - virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); - virtual void EmitCFIEscape(StringRef Values); - virtual void EmitCFISignalFrame(); - virtual void EmitCFIUndefined(int64_t Register); - virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); - - virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); - virtual void EmitWin64EHEndProc(); - virtual void EmitWin64EHStartChained(); - virtual void EmitWin64EHEndChained(); - virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except); - virtual void EmitWin64EHHandlerData(); - virtual void EmitWin64EHPushReg(unsigned Register); - virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); - virtual void EmitWin64EHAllocStack(unsigned Size); - virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); - virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); - virtual void EmitWin64EHPushFrame(bool Code); - virtual void EmitWin64EHEndProlog(); - - /// EmitInstruction - Emit the given @p Instruction into the current - /// section. - virtual void EmitInstruction(const MCInst &Inst) = 0; - - /// \brief Set the bundle alignment mode from now on in the section. - /// The argument is the power of 2 to which the alignment is set. The - /// value 0 means turn the bundle alignment off. - virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; - - /// \brief The following instructions are a bundle-locked group. - /// - /// \param AlignToEnd - If true, the bundle-locked group will be aligned to - /// the end of a bundle. - virtual void EmitBundleLock(bool AlignToEnd) = 0; - - /// \brief Ends a bundle-locked group. - virtual void EmitBundleUnlock() = 0; - - /// EmitRawText - If this file is backed by a assembly streamer, this dumps - /// the specified string in the output .s file. This capability is - /// indicated by the hasRawTextSupport() predicate. By default this aborts. - virtual void EmitRawText(StringRef String); - void EmitRawText(const Twine &String); - - /// ARM-related methods. - /// FIXME: Eventually we should have some "target MC streamer" and move - /// these methods there. - virtual void EmitFnStart(); - virtual void EmitFnEnd(); - virtual void EmitCantUnwind(); - virtual void EmitPersonality(const MCSymbol *Personality); - virtual void EmitHandlerData(); - virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); - virtual void EmitPad(int64_t Offset); - virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList, - bool isVector); - - /// PPC-related methods. - /// FIXME: Eventually replace it with some "target MC streamer" and move - /// these methods there. - virtual void EmitTCEntry(const MCSymbol &S); - - /// FinishImpl - Streamer specific finalization. - virtual void FinishImpl() = 0; - /// Finish - Finish emission of machine code. - void Finish(); - }; - - /// createNullStreamer - Create a dummy machine code streamer, which does - /// nothing. This is useful for timing the assembler front end. - MCStreamer *createNullStreamer(MCContext &Ctx); - - /// createAsmStreamer - Create a machine code streamer which will print out - /// assembly for the native target, suitable for compiling with a native - /// assembler. - /// - /// \param InstPrint - If given, the instruction printer to use. If not given - /// the MCInst representation will be printed. This method takes ownership of - /// InstPrint. - /// - /// \param CE - If given, a code emitter to use to show the instruction - /// encoding inline with the assembly. This method takes ownership of \p CE. - /// - /// \param TAB - If given, a target asm backend to use to show the fixup - /// information in conjunction with encoding information. This method takes - /// ownership of \p TAB. - /// - /// \param ShowInst - Whether to show the MCInst representation inline with - /// the assembly. - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, - bool useLoc, - bool useCFI, - bool useDwarfDirectory, - MCInstPrinter *InstPrint = 0, - MCCodeEmitter *CE = 0, - MCAsmBackend *TAB = 0, - bool ShowInst = false); - - /// createMachOStreamer - Create a machine code streamer which will generate - /// Mach-O format object files. - /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); + /// EmitAssemblerFlag - Note in the output the specified @p Flag. + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + + /// EmitLinkerOptions - Emit the given list @p Options of strings as linker + /// options into the output. + virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {} + + /// EmitDataRegion - Note in the output the specified region @p Kind. + virtual void EmitDataRegion(MCDataRegionType Kind) {} + + /// EmitThumbFunc - Note in the output that the specified @p Func is + /// a Thumb mode function (ARM target only). + virtual void EmitThumbFunc(MCSymbol *Func) = 0; - /// createWinCOFFStreamer - Create a machine code streamer which will - /// generate Microsoft COFF format object files. + /// getOrCreateSymbolData - Get symbol data for given symbol. + virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + + /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// symbol = value + /// + /// The assignment generates no code, but has the side effect of binding the + /// value in the current context. For the assembly streamer, this prints the + /// binding into the .s file. /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createWinCOFFStreamer(MCContext &Ctx, - MCAsmBackend &TAB, - MCCodeEmitter &CE, raw_ostream &OS, - bool RelaxAll = false); + /// @param Symbol - The symbol being assigned to. + /// @param Value - The value for the symbol. + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; - /// createELFStreamer - Create a machine code streamer which will generate - /// ELF format object files. - MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll, bool NoExecStack); + /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// .weakref alias, symbol + /// + /// @param Alias - The alias that is being created. + /// @param Symbol - The symbol being aliased. + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; + + /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) = 0; + + /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. + /// + /// @param Symbol - The symbol to have its n_desc field set. + /// @param DescValue - The value to set into the n_desc field. + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; + + /// BeginCOFFSymbolDef - Start emitting COFF symbol definition + /// + /// @param Symbol - The symbol to have its External & Type fields set. + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; + + /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. + /// + /// @param StorageClass - The storage class the symbol should have. + virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; - /// createPureStreamer - Create a machine code streamer which will generate - /// "pure" MC object files, for use with MC-JIT and testing tools. + /// EmitCOFFSymbolType - Emit the type of the symbol. /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE); + /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + virtual void EmitCOFFSymbolType(int Type) = 0; + + /// EndCOFFSymbolDef - Marks the end of the symbol definition. + virtual void EndCOFFSymbolDef() = 0; + + /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. + /// + /// @param Symbol - Symbol the section relative realocation should point to. + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); + + /// EmitELFSize - Emit an ELF .size directive. + /// + /// This corresponds to an assembler statement such as: + /// .size symbol, expression + /// + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; + + /// EmitCommonSymbol - Emit a common symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + /// @param ByteAlignment - The alignment of the symbol if + /// non-zero. This must be a power of 2. + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 0; + + /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + /// @param ByteAlignment - The alignment of the common symbol in bytes. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 0; + + /// EmitZerofill - Emit the zerofill section and an optional symbol. + /// + /// @param Section - The zerofill section to create and or to put the symbol + /// @param Symbol - The zerofill symbol to emit, if non-NULL. + /// @param Size - The size of the zerofill symbol. + /// @param ByteAlignment - The alignment of the zerofill symbol if + /// non-zero. This must be a power of 2 on some targets. + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + uint64_t Size = 0, unsigned ByteAlignment = 0) = 0; + + /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. + /// + /// @param Section - The thread local common section. + /// @param Symbol - The thread local common symbol to emit. + /// @param Size - The size of the symbol. + /// @param ByteAlignment - The alignment of the thread local common symbol + /// if non-zero. This must be a power of 2 on some targets. + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) = 0; + + /// @} + /// @name Generating Data + /// @{ + + /// EmitBytes - Emit the bytes in \p Data into the output. + /// + /// This is used to implement assembler directives such as .byte, .ascii, + /// etc. + virtual void EmitBytes(StringRef Data) = 0; + + /// EmitValue - Emit the expression @p Value into the output as a native + /// integer of the given @p Size bytes. + /// + /// This is used to implement assembler directives such as .word, .quad, + /// etc. + /// + /// @param Value - The value to emit. + /// @param Size - The size of the integer (in bytes) to emit. This must + /// match a native machine width. + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) = 0; + + void EmitValue(const MCExpr *Value, unsigned Size); + + /// EmitIntValue - Special case of EmitValue that avoids the client having + /// to pass in a MCExpr for constant integers. + virtual void EmitIntValue(uint64_t Value, unsigned Size); + + /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO + /// this is done by producing + /// foo = value + /// .long foo + void EmitAbsValue(const MCExpr *Value, unsigned Size); + + virtual void EmitULEB128Value(const MCExpr *Value) = 0; + + virtual void EmitSLEB128Value(const MCExpr *Value) = 0; + + /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0); + + /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitSLEB128IntValue(int64_t Value); + + /// EmitSymbolValue - Special case of EmitValue that avoids the client + /// having to pass in a MCExpr for MCSymbols. + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size); + + /// EmitGPRel64Value - Emit the expression @p Value into the output as a + /// gprel64 (64-bit GP relative) value. + /// + /// This is used to implement assembler directives such as .gpdword on + /// targets that support them. + virtual void EmitGPRel64Value(const MCExpr *Value); + + /// EmitGPRel32Value - Emit the expression @p Value into the output as a + /// gprel32 (32-bit GP relative) value. + /// + /// This is used to implement assembler directives such as .gprel32 on + /// targets that support them. + virtual void EmitGPRel32Value(const MCExpr *Value); + + /// EmitFill - Emit NumBytes bytes worth of the value specified by + /// FillValue. This implements directives such as '.space'. + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); + + /// \brief Emit NumBytes worth of zeros. + /// This function properly handles data in virtual sections. + virtual void EmitZeros(uint64_t NumBytes); + + /// EmitValueToAlignment - Emit some number of copies of @p Value until + /// the byte alignment @p ByteAlignment is reached. + /// + /// If the number of bytes need to emit for the alignment is not a multiple + /// of @p ValueSize, then the contents of the emitted fill bytes is + /// undefined. + /// + /// This used to implement the .align assembler directive. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param Value - The value to use when filling bytes. + /// @param ValueSize - The size of the integer (in bytes) to emit for + /// @p Value. This must match a native machine width. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment + /// is reached. + /// + /// This used to align code where the alignment bytes may be executed. This + /// can emit different bytes for different sizes to optimize execution. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitValueToOffset - Emit some number of copies of @p Value until the + /// byte offset @p Offset is reached. + /// + /// This is used to implement assembler directives such as .org. + /// + /// @param Offset - The offset to reach. This may be an expression, but the + /// expression must be associated with the current section. + /// @param Value - The value to use when filling bytes. + /// @return false on success, true if the offset was invalid. + virtual bool EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) = 0; + + /// @} + + /// EmitFileDirective - Switch to a new logical file. This is used to + /// implement the '.file "foo.c"' assembler directive. + virtual void EmitFileDirective(StringRef Filename) = 0; + + /// Emit the "identifiers" directive. This implements the + /// '.ident "version foo"' assembler directive. + virtual void EmitIdent(StringRef IdentString) {} + + /// EmitDwarfFileDirective - Associate a filename with a specified logical + /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler + /// directive. + virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, + StringRef Filename, unsigned CUID = 0); + + /// EmitDwarfLocDirective - This implements the DWARF2 + // '.loc fileno lineno ...' assembler directive. + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName); + + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize) = 0; + + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) {} + + void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, + int PointerSize); + + virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); + virtual void EmitCFISections(bool EH, bool Debug); + void EmitCFIStartProc(); + void EmitCFIEndProc(); + virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual void EmitCFIDefCfaOffset(int64_t Offset); + virtual void EmitCFIDefCfaRegister(int64_t Register); + virtual void EmitCFIOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIRememberState(); + virtual void EmitCFIRestoreState(); + virtual void EmitCFISameValue(int64_t Register); + virtual void EmitCFIRestore(int64_t Register); + virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); + virtual void EmitCFIEscape(StringRef Values); + virtual void EmitCFISignalFrame(); + virtual void EmitCFIUndefined(int64_t Register); + virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); + virtual void EmitCFIWindowSave(); + + virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); + virtual void EmitWin64EHEndProc(); + virtual void EmitWin64EHStartChained(); + virtual void EmitWin64EHEndChained(); + virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, + bool Except); + virtual void EmitWin64EHHandlerData(); + virtual void EmitWin64EHPushReg(unsigned Register); + virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); + virtual void EmitWin64EHAllocStack(unsigned Size); + virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); + virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); + virtual void EmitWin64EHPushFrame(bool Code); + virtual void EmitWin64EHEndProlog(); + + /// EmitInstruction - Emit the given @p Instruction into the current + /// section. + virtual void EmitInstruction(const MCInst &Inst) = 0; + + /// \brief Set the bundle alignment mode from now on in the section. + /// The argument is the power of 2 to which the alignment is set. The + /// value 0 means turn the bundle alignment off. + virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; + + /// \brief The following instructions are a bundle-locked group. + /// + /// \param AlignToEnd - If true, the bundle-locked group will be aligned to + /// the end of a bundle. + virtual void EmitBundleLock(bool AlignToEnd) = 0; + + /// \brief Ends a bundle-locked group. + virtual void EmitBundleUnlock() = 0; + + /// EmitRawText - If this file is backed by a assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. By default this aborts. + void EmitRawText(const Twine &String); + + /// Flush - Causes any cached state to be written out. + virtual void Flush() {} + + /// FinishImpl - Streamer specific finalization. + virtual void FinishImpl() = 0; + /// Finish - Finish emission of machine code. + void Finish(); +}; + +/// createNullStreamer - Create a dummy machine code streamer, which does +/// nothing. This is useful for timing the assembler front end. +MCStreamer *createNullStreamer(MCContext &Ctx); + +/// createAsmStreamer - Create a machine code streamer which will print out +/// assembly for the native target, suitable for compiling with a native +/// assembler. +/// +/// \param InstPrint - If given, the instruction printer to use. If not given +/// the MCInst representation will be printed. This method takes ownership of +/// InstPrint. +/// +/// \param CE - If given, a code emitter to use to show the instruction +/// encoding inline with the assembly. This method takes ownership of \p CE. +/// +/// \param TAB - If given, a target asm backend to use to show the fixup +/// information in conjunction with encoding information. This method takes +/// ownership of \p TAB. +/// +/// \param ShowInst - Whether to show the MCInst representation inline with +/// the assembly. +MCStreamer *createAsmStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, + formatted_raw_ostream &OS, bool isVerboseAsm, + bool useLoc, bool useCFI, bool useDwarfDirectory, + MCInstPrinter *InstPrint = 0, + MCCodeEmitter *CE = 0, MCAsmBackend *TAB = 0, + bool ShowInst = false); + +/// createMachOStreamer - Create a machine code streamer which will generate +/// Mach-O format object files. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll = false); + +/// createWinCOFFStreamer - Create a machine code streamer which will +/// generate Microsoft COFF format object files. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createWinCOFFStreamer(MCContext &Ctx, MCAsmBackend &TAB, + MCCodeEmitter &CE, raw_ostream &OS, + bool RelaxAll = false); + +/// createELFStreamer - Create a machine code streamer which will generate +/// ELF format object files. +MCStreamer *createELFStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *CE, bool RelaxAll, + bool NoExecStack); + +/// createPureStreamer - Create a machine code streamer which will generate +/// "pure" MC object files, for use with MC-JIT and testing tools. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE); } // end namespace llvm diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 346fb2d..01e8236 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -72,6 +72,9 @@ public: /// feature string). Recompute feature bits and scheduling model. void InitMCProcessorInfo(StringRef CPU, StringRef FS); + /// InitCPUSchedModel - Recompute scheduling model based on CPU. + void InitCPUSchedModel(StringRef CPU); + /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. uint64_t ToggleFeature(uint64_t FB); diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index ebcbd5b..d132a73 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -11,6 +11,7 @@ #define LLVM_MC_TARGETPARSER_H #include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCExpr.h" namespace llvm { class MCStreamer; @@ -174,6 +175,14 @@ public: virtual void convertToMapAndConstraints(unsigned Kind, const SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0; + + virtual const MCExpr *applyModifierToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind, + MCContext &Ctx) { + return 0; + } + + virtual void onLabelParsed(MCSymbol *Symbol) { }; }; } // End llvm namespace diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index f13e7d5..213481c 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -17,6 +17,7 @@ namespace llvm { class raw_ostream; class MCWinCOFFObjectTargetWriter { + virtual void anchor(); const unsigned Machine; protected: diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h index c4a9660..b3fbee7 100644 --- a/include/llvm/MC/MachineLocation.h +++ b/include/llvm/MC/MachineLocation.h @@ -16,6 +16,9 @@ #ifndef LLVM_MC_MACHINELOCATION_H #define LLVM_MC_MACHINELOCATION_H +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + namespace llvm { class MCSymbol; @@ -25,7 +28,7 @@ private: unsigned Register; // gcc/gdb register number. int Offset; // Displacement if not register. public: - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // The target register number for an abstract frame pointer. The value is // an arbitrary value that doesn't collide with any real target register. VirtualFP = ~0U @@ -44,7 +47,8 @@ public: Offset == Other.Offset; } - // Accessors + // Accessors. + /// \return true iff this is a register-indirect location. bool isIndirect() const { return !IsRegister; } bool isReg() const { return IsRegister; } unsigned getReg() const { return Register; } diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 8862c8b..d0735cc 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -37,9 +37,9 @@ struct SubtargetFeatureKV { uint64_t Value; // K-V integer value uint64_t Implies; // K-V bit mask - // Compare routine for std binary search - bool operator<(const SubtargetFeatureKV &S) const { - return strcmp(Key, S.Key) < 0; + // Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; } }; @@ -52,9 +52,9 @@ struct SubtargetInfoKV { const char *Key; // K-V key string const void *Value; // K-V pointer value - // Compare routine for std binary search - bool operator<(const SubtargetInfoKV &S) const { - return strcmp(Key, S.Key) < 0; + // Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; } }; @@ -99,8 +99,7 @@ public: // Dump feature info. void dump() const; - /// Retrieve a formatted string of the default features for the specified - /// target triple. + /// Adds the default features for the specified target triple. void getDefaultSubtargetFeatures(const Triple& Triple); }; diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 2190067..e05ae6c 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -23,6 +23,8 @@ namespace llvm { class ArrayRef; namespace object { +class ImportDirectoryEntryRef; +typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator; /// The DOS compatible header at the front of all PE/COFF executables. struct dos_header { @@ -55,6 +57,8 @@ struct coff_file_header { support::ulittle32_t NumberOfSymbols; support::ulittle16_t SizeOfOptionalHeader; support::ulittle16_t Characteristics; + + bool isImportLibrary() const { return NumberOfSections == 0xffff; } }; /// The 32-bit PE header that follows the COFF header. @@ -137,6 +141,22 @@ struct import_directory_table_entry { support::ulittle32_t ImportAddressTableRVA; }; +struct import_lookup_table_entry32 { + support::ulittle32_t data; + + bool isOrdinal() const { return data & 0x80000000; } + + uint16_t getOrdinal() const { + assert(isOrdinal() && "ILT entry is not an ordinal!"); + return data & 0xFFFF; + } + + uint32_t getHintNameRVA() const { + assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); + return data; + } +}; + struct coff_symbol { struct StringTableOffset { support::ulittle32_t Zeroes; @@ -184,6 +204,12 @@ struct coff_relocation { support::ulittle16_t Type; }; +struct coff_aux_weak_external { + support::ulittle32_t TagIndex; + support::ulittle32_t Characteristics; + char Unused[10]; +}; + struct coff_aux_section_definition { support::ulittle32_t Length; support::ulittle16_t NumberOfRelocations; @@ -196,6 +222,7 @@ struct coff_aux_section_definition { class COFFObjectFile : public ObjectFile { private: + friend class ImportDirectoryEntryRef; const coff_file_header *COFFHeader; const pe32_header *PE32Header; const data_directory *DataDirectory; @@ -203,6 +230,8 @@ private: const coff_symbol *SymbolTable; const char *StringTable; uint32_t StringTableSize; + const import_directory_table_entry *ImportDirectory; + uint32_t NumberOfImportDirectory; error_code getString(uint32_t offset, StringRef &Res) const; @@ -210,13 +239,15 @@ private: const coff_section *toSec(DataRefImpl Sec) const; const coff_relocation *toRel(DataRefImpl Rel) const; + error_code initSymbolTablePtr(); + error_code initImportTablePtr(); + protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, @@ -239,8 +270,8 @@ protected: bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; @@ -281,6 +312,9 @@ public: virtual unsigned getArch() const; virtual StringRef getLoadName() const; + import_directory_iterator import_directory_begin() const; + import_directory_iterator import_directory_end() const; + error_code getHeader(const coff_file_header *&Res) const; error_code getCOFFHeader(const coff_file_header *&Res) const; error_code getPE32Header(const pe32_header *&Res) const; @@ -301,12 +335,37 @@ public: error_code getSectionContents(const coff_section *Sec, ArrayRef<uint8_t> &Res) const; + error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; + error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + static inline bool classof(const Binary *v) { return v->isCOFF(); } }; -} -} +// The iterator for the import directory table. +class ImportDirectoryEntryRef { +public: + ImportDirectoryEntryRef() : OwningObject(0) {} + ImportDirectoryEntryRef(DataRefImpl ImportDirectory, + const COFFObjectFile *Owner) + : ImportDirectoryPimpl(ImportDirectory), OwningObject(Owner) {} + + bool operator==(const ImportDirectoryEntryRef &Other) const; + error_code getNext(ImportDirectoryEntryRef &Result) const; + error_code getName(StringRef &Result) const; + + error_code + getImportTableEntry(const import_directory_table_entry *&Result) const; + + error_code + getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; + +private: + DataRefImpl ImportDirectoryPimpl; + const COFFObjectFile *OwningObject; +}; +} // end namespace object +} // end namespace llvm #endif diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 2063809..6c000bb 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -7,23 +7,26 @@ // //===----------------------------------------------------------------------===// // -// This file declares the ELFObjectFile template class. +// This file declares the ELFFile template class. // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJECT_ELF_H #define LLVM_OBJECT_ELF_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -35,22 +38,9 @@ namespace llvm { namespace object { -using support::endianness; +StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -struct ELFType { - static const endianness TargetEndianness = target_endianness; - static const std::size_t MaxAlignment = max_alignment; - static const bool Is64Bits = is64Bits; -}; - -template<typename T, int max_align> -struct MaximumAlignment { - enum {value = AlignOf<T>::Alignment > max_align ? max_align - : AlignOf<T>::Alignment}; -}; - -// Subclasses of ELFObjectFile may need this for template instantiation +// Subclasses of ELFFile may need this for template instantiation inline std::pair<unsigned char, unsigned char> getElfArchType(MemoryBuffer *Object) { if (Object->getBufferSize() < ELF::EI_NIDENT) @@ -59,442 +49,15 @@ getElfArchType(MemoryBuffer *Object) { (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); } -// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -template<endianness target_endianness, std::size_t max_alignment> -struct ELFDataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - <uint16_t, target_endianness, - MaximumAlignment<uint16_t, max_alignment>::value> Elf_Half; - typedef support::detail::packed_endian_specific_integral - <uint32_t, target_endianness, - MaximumAlignment<uint32_t, max_alignment>::value> Elf_Word; - typedef support::detail::packed_endian_specific_integral - <int32_t, target_endianness, - MaximumAlignment<int32_t, max_alignment>::value> Elf_Sword; - typedef support::detail::packed_endian_specific_integral - <uint64_t, target_endianness, - MaximumAlignment<uint64_t, max_alignment>::value> Elf_Xword; - typedef support::detail::packed_endian_specific_integral - <int64_t, target_endianness, - MaximumAlignment<int64_t, max_alignment>::value> Elf_Sxword; -}; - -template<class ELFT> -struct ELFDataTypeTypedefHelper; - -/// ELF 32bit types. -template<endianness TargetEndianness, std::size_t MaxAlign> -struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, false> > - : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { - typedef uint32_t value_type; - typedef support::detail::packed_endian_specific_integral - <value_type, TargetEndianness, - MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - <value_type, TargetEndianness, - MaximumAlignment<value_type, MaxAlign>::value> Elf_Off; -}; - -/// ELF 64bit types. -template<endianness TargetEndianness, std::size_t MaxAlign> -struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, true> > - : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { - typedef uint64_t value_type; - typedef support::detail::packed_endian_specific_integral - <value_type, TargetEndianness, - MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - <value_type, TargetEndianness, - MaximumAlignment<value_type, MaxAlign>::value> Elf_Off; -}; - -// I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ -typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Addr Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Off Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Half Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Word Elf_Word; \ -typedef typename \ - ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Sword Elf_Sword; \ -typedef typename \ - ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Xword Elf_Xword; \ -typedef typename \ - ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Sxword Elf_Sxword; - -#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ - LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ - ELFT::Is64Bits) - -// Section header. -template<class ELFT> -struct Elf_Shdr_Base; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Word sh_name; // Section name (index into string table) - Elf_Word sh_type; // Section type (SHT_*) - Elf_Word sh_flags; // Section flags (SHF_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Word sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Word sh_addralign;// Section address alignment - Elf_Word sh_entsize; // Size of records contained within the section -}; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Word sh_name; // Section name (index into string table) - Elf_Word sh_type; // Section type (SHT_*) - Elf_Xword sh_flags; // Section flags (SHF_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Xword sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Xword sh_addralign;// Section address alignment - Elf_Xword sh_entsize; // Size of records contained within the section -}; - -template<class ELFT> -struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { - using Elf_Shdr_Base<ELFT>::sh_entsize; - using Elf_Shdr_Base<ELFT>::sh_size; - - /// @brief Get the number of entities this section contains if it has any. - unsigned getEntityCount() const { - if (sh_entsize == 0) - return 0; - return sh_size / sh_entsize; - } -}; - -template<class ELFT> -struct Elf_Sym_Base; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Word st_name; // Symbol name (index into string table) - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Word st_size; // Size of the symbol - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in -}; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Word st_name; // Symbol name (index into string table) - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Xword st_size; // Size of the symbol -}; - -template<class ELFT> -struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { - using Elf_Sym_Base<ELFT>::st_info; - - // These accessors and mutators correspond to the ELF32_ST_BIND, - // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: - unsigned char getBinding() const { return st_info >> 4; } - unsigned char getType() const { return st_info & 0x0f; } - void setBinding(unsigned char b) { setBindingAndType(b, getType()); } - void setType(unsigned char t) { setBindingAndType(getBinding(), t); } - void setBindingAndType(unsigned char b, unsigned char t) { - st_info = (b << 4) + (t & 0x0f); - } -}; - -/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section -/// (.gnu.version). This structure is identical for ELF32 and ELF64. -template<class ELFT> -struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) -}; - -template<class ELFT> -struct Elf_Verdaux_Impl; - -/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section -/// (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template<class ELFT> -struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; - Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) - Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) - Elf_Half vd_ndx; // Version index, used in .gnu.version entries - Elf_Half vd_cnt; // Number of Verdaux entries - Elf_Word vd_hash; // Hash of name - Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) - Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) - - /// Get the first Verdaux entry for this Verdef. - const Elf_Verdaux *getAux() const { - return reinterpret_cast<const Elf_Verdaux*>((const char*)this + vd_aux); - } -}; - -/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef -/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template<class ELFT> -struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word vda_name; // Version name (offset in string table) - Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) -}; - -/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed -/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template<class ELFT> -struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) - Elf_Half vn_cnt; // Number of associated Vernaux entries - Elf_Word vn_file; // Library name (string table offset) - Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) - Elf_Word vn_next; // Offset to next Verneed entry (in bytes) -}; - -/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed -/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template<class ELFT> -struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word vna_hash; // Hash of dependency name - Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) - Elf_Half vna_other; // Version index, used in .gnu.version entries - Elf_Word vna_name; // Dependency name - Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) -}; - -/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic -/// table section (.dynamic) look like. -template<class ELFT> -struct Elf_Dyn_Base; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Sword d_tag; - union { - Elf_Word d_val; - Elf_Addr d_ptr; - } d_un; -}; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Sxword d_tag; - union { - Elf_Xword d_val; - Elf_Addr d_ptr; - } d_un; -}; - -/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. -template<class ELFT> -struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { - using Elf_Dyn_Base<ELFT>::d_tag; - using Elf_Dyn_Base<ELFT>::d_un; - int64_t getTag() const { return d_tag; } - uint64_t getVal() const { return d_un.d_val; } - uint64_t getPtr() const { return d_un.ptr; } -}; - -// Elf_Rel: Elf Relocation -template<class ELFT, bool isRela> -struct Elf_Rel_Base; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - - uint32_t getRInfo(bool isMips64EL) const { - assert(!isMips64EL); - return r_info; - } - void setRInfo(uint32_t R) { - r_info = R; - } -}; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - - uint64_t getRInfo(bool isMips64EL) const { - uint64_t t = r_info; - if (!isMips64EL) - return t; - // Mips64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little endian 32 bit number followed - // by a 32 bit big endian number. - return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | - ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); - } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; - } -}; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - Elf_Sword r_addend; // Compute value for relocatable field by adding this - - uint32_t getRInfo(bool isMips64EL) const { - assert(!isMips64EL); - return r_info; - } - void setRInfo(uint32_t R) { - r_info = R; - } -}; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. - - uint64_t getRInfo(bool isMips64EL) const { - // Mips64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little endian 32 bit number followed - // by a 32 bit big endian number. - uint64_t t = r_info; - if (!isMips64EL) - return t; - return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | - ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); - } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; - } -}; - -template<class ELFT, bool isRela> -struct Elf_Rel_Impl; - -template<endianness TargetEndianness, std::size_t MaxAlign, bool isRela> -struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>, isRela> - : Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - - // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, - // and ELF64_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return (uint32_t) (this->getRInfo(isMips64EL) >> 32); - } - uint32_t getType(bool isMips64EL) const { - return (uint32_t) (this->getRInfo(isMips64EL) & 0xffffffffL); - } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, uint32_t t) { - this->setRInfo(((uint64_t)s << 32) + (t&0xffffffffL)); - } -}; - -template<endianness TargetEndianness, std::size_t MaxAlign, bool isRela> -struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>, isRela> - : Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - - // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, - // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return this->getRInfo(isMips64EL) >> 8; - } - unsigned char getType(bool isMips64EL) const { - return (unsigned char) (this->getRInfo(isMips64EL) & 0x0ff); - } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, unsigned char t) { - this->setRInfo((s << 8) + t); - } -}; - -template<class ELFT> -struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes - Elf_Half e_type; // Type of file (see ET_*) - Elf_Half e_machine; // Required architecture for this file (see EM_*) - Elf_Word e_version; // Must be equal to 1 - Elf_Addr e_entry; // Address to jump to in order to start program - Elf_Off e_phoff; // Program header table's file offset, in bytes - Elf_Off e_shoff; // Section header table's file offset, in bytes - Elf_Word e_flags; // Processor-specific flags - Elf_Half e_ehsize; // Size of ELF header, in bytes - Elf_Half e_phentsize;// Size of an entry in the program header table - Elf_Half e_phnum; // Number of entries in the program header table - Elf_Half e_shentsize;// Size of an entry in the section header table - Elf_Half e_shnum; // Number of entries in the section header table - Elf_Half e_shstrndx; // Section header table index of section name - // string table - bool checkMagic() const { - return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; - } - unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } - unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } -}; - -template<class ELFT> -struct Elf_Phdr_Impl; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Word p_type; // Type of segment - Elf_Off p_offset; // FileOffset where segment is located, in bytes - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Word p_flags; // Segment flags - Elf_Word p_align; // Segment alignment constraint -}; - -template<endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Word p_type; // Type of segment - Elf_Word p_flags; // Segment flags - Elf_Off p_offset; // FileOffset where segment is located, in bytes - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Xword p_align; // Segment alignment constraint -}; - -template<class ELFT> -class ELFObjectFile : public ObjectFile { +template <class ELFT> +class ELFFile { +public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + typedef typename conditional<ELFT::Is64Bits, + uint64_t, uint32_t>::type uintX_t; -public: /// \brief Iterate over constant sized entities. - template<class EntT> + template <class EntT> class ELFEntityIterator { public: typedef ptrdiff_t difference_type; @@ -505,9 +68,8 @@ public: /// \brief Default construct iterator. ELFEntityIterator() : EntitySize(0), Current(0) {} - ELFEntityIterator(uint64_t EntSize, const char *Start) - : EntitySize(EntSize) - , Current(Start) {} + ELFEntityIterator(uintX_t EntSize, const char *Start) + : EntitySize(EntSize), Current(Start) {} reference operator *() { assert(Current && "Attempted to dereference an invalid iterator!"); @@ -547,14 +109,16 @@ public: difference_type operator -(const ELFEntityIterator &Other) const { assert(EntitySize == Other.EntitySize && - "Subtracting iterators of different EntitiySize!"); + "Subtracting iterators of different EntitySize!"); return (Current - Other.Current) / EntitySize; } const char *get() const { return Current; } + uintX_t getEntSize() const { return EntitySize; } + private: - uint64_t EntitySize; + uintX_t EntitySize; const char *Current; }; @@ -570,40 +134,141 @@ public: typedef Elf_Verneed_Impl<ELFT> Elf_Verneed; typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux; typedef Elf_Versym_Impl<ELFT> Elf_Versym; - typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_iterator; - typedef ELFEntityIterator<const Elf_Sym> Elf_Sym_iterator; + typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_Iter; typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter; typedef ELFEntityIterator<const Elf_Rel> Elf_Rel_Iter; + typedef ELFEntityIterator<const Elf_Shdr> Elf_Shdr_Iter; -protected: - // This flag is used for classof, to distinguish ELFObjectFile from - // its subclass. If more subclasses will be created, this flag will - // have to become an enum. - bool isDyldELFObject; + /// \brief Archive files are 2 byte aligned, so we need this for + /// PointerIntPair to work. + template <typename T> + class ArchivePointerTypeTraits { + public: + static inline const void *getAsVoidPointer(T *P) { return P; } + static inline T *getFromVoidPointer(const void *P) { + return static_cast<T *>(P); + } + enum { NumLowBitsAvailable = 1 }; + }; + + class Elf_Sym_Iter { + public: + typedef ptrdiff_t difference_type; + typedef const Elf_Sym value_type; + typedef std::random_access_iterator_tag iterator_category; + typedef value_type &reference; + typedef value_type *pointer; + + /// \brief Default construct iterator. + Elf_Sym_Iter() : EntitySize(0), Current(0, false) {} + Elf_Sym_Iter(uintX_t EntSize, const char *Start, bool IsDynamic) + : EntitySize(EntSize), Current(Start, IsDynamic) {} + + reference operator*() { + assert(Current.getPointer() && + "Attempted to dereference an invalid iterator!"); + return *reinterpret_cast<pointer>(Current.getPointer()); + } + + pointer operator->() { + assert(Current.getPointer() && + "Attempted to dereference an invalid iterator!"); + return reinterpret_cast<pointer>(Current.getPointer()); + } + + bool operator==(const Elf_Sym_Iter &Other) { + return Current == Other.Current; + } + + bool operator!=(const Elf_Sym_Iter &Other) { return !(*this == Other); } + + Elf_Sym_Iter &operator++() { + assert(Current.getPointer() && + "Attempted to increment an invalid iterator!"); + Current.setPointer(Current.getPointer() + EntitySize); + return *this; + } + + Elf_Sym_Iter operator++(int) { + Elf_Sym_Iter Tmp = *this; + ++*this; + return Tmp; + } + + Elf_Sym_Iter operator+(difference_type Dist) { + assert(Current.getPointer() && + "Attempted to increment an invalid iterator!"); + Current.setPointer(Current.getPointer() + EntitySize * Dist); + return *this; + } + + Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) { + EntitySize = Other.EntitySize; + Current = Other.Current; + return *this; + } + + difference_type operator-(const Elf_Sym_Iter &Other) const { + assert(EntitySize == Other.EntitySize && + "Subtracting iterators of different EntitySize!"); + return (Current.getPointer() - Other.Current.getPointer()) / EntitySize; + } + + const char *get() const { return Current.getPointer(); } + + bool isDynamic() const { return Current.getInt(); } + + uintX_t getEntSize() const { return EntitySize; } + + private: + uintX_t EntitySize; + PointerIntPair<const char *, 1, bool, + ArchivePointerTypeTraits<const char> > Current; + }; private: + typedef SmallVector<const Elf_Shdr *, 2> Sections_t; + typedef DenseMap<unsigned, unsigned> IndexMap_t; + + MemoryBuffer *Buf; + + const uint8_t *base() const { + return reinterpret_cast<const uint8_t *>(Buf->getBufferStart()); + } + const Elf_Ehdr *Header; const Elf_Shdr *SectionHeaderTable; const Elf_Shdr *dot_shstrtab_sec; // Section header string table. const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. + const Elf_Shdr *dot_symtab_sec; // Symbol table section. - int SymbolTableIndex; - int DynamicSymbolTableIndex; - DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; + const Elf_Shdr *SymbolTableSectionHeaderIndex; + DenseMap<const Elf_Sym *, ELF::Elf64_Word> ExtendedSymbolTable; - const Elf_Shdr *dot_dynamic_sec; // .dynamic const Elf_Shdr *dot_gnu_version_sec; // .gnu.version const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d + /// \brief Represents a region described by entries in the .dynamic table. + struct DynRegionInfo { + DynRegionInfo() : Addr(0), Size(0), EntSize(0) {} + /// \brief Address in current address space. + const void *Addr; + /// \brief Size in bytes of the region. + uintX_t Size; + /// \brief Size of each entity in the region. + uintX_t EntSize; + }; + + DynRegionInfo DynamicRegion; + DynRegionInfo DynHashRegion; + DynRegionInfo DynStrRegion; + DynRegionInfo DynSymRegion; + // Pointer to SONAME entry in dynamic string table // This is set the first time getLoadName is called. mutable const char *dt_soname; -private: - uint64_t getROffset(DataRefImpl Rel) const; - // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair<const void*, 1> { @@ -630,99 +295,29 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; - /// @brief Get the relocation section that contains \a Rel. - const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return getSection(Rel.d.a); - } - public: - bool isRelocationHasAddend(DataRefImpl Rel) const; template<typename T> const T *getEntry(uint32_t Section, uint32_t Entry) const; - template<typename T> - const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; - const Elf_Shdr *getSection(DataRefImpl index) const; - const Elf_Shdr *getSection(uint32_t index) const; - const Elf_Rel *getRel(DataRefImpl Rel) const; - const Elf_Rela *getRela(DataRefImpl Rela) const; + template <typename T> + const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; const char *getString(uint32_t section, uint32_t offset) const; const char *getString(const Elf_Shdr *section, uint32_t offset) const; - error_code getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Version, - bool &IsDefault) const; + const char *getDynamicString(uintX_t Offset) const; + ErrorOr<StringRef> getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *Symb, + bool &IsDefault) const; void VerifyStrTab(const Elf_Shdr *sh) const; -protected: - const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? - void validateSymbol(DataRefImpl Symb) const; - StringRef getRelocationTypeName(uint32_t Type) const; + StringRef getRelocationTypeName(uint32_t Type) const; + void getRelocationTypeName(uint32_t Type, + SmallVectorImpl<char> &Result) const; -public: - error_code getSymbolName(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Res) const; - error_code getSectionName(const Elf_Shdr *section, - StringRef &Res) const; - const Elf_Dyn *getDyn(DataRefImpl DynData) const; - error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const; - uint64_t getSymbolIndex(const Elf_Sym *sym) const; - error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; -protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; - virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; - virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const; - virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; + /// \brief Get the symbol table section and symbol for a given relocation. + template <class RelT> + std::pair<const Elf_Shdr *, const Elf_Sym *> + getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; -public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFFile(MemoryBuffer *Object, error_code &ec); bool isMips64EL() const { return Header->e_machine == ELF::EM_MIPS && @@ -730,65 +325,51 @@ public: Header->getDataEncoding() == ELF::ELFDATA2LSB; } - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; + Elf_Shdr_Iter begin_sections() const; + Elf_Shdr_Iter end_sections() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + Elf_Sym_Iter begin_symbols() const; + Elf_Sym_Iter end_symbols() const; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; - - const Elf_Shdr *getDynamicSymbolTableSectionHeader() const { - return getSection(DynamicSymbolTableIndex); - } - - const Elf_Shdr *getDynamicStringTableSectionHeader() const { - return dot_dynstr_sec; - } - - Elf_Dyn_iterator begin_dynamic_table() const; + Elf_Dyn_Iter begin_dynamic_table() const; /// \param NULLEnd use one past the first DT_NULL entry as the end instead of /// the section size. - Elf_Dyn_iterator end_dynamic_table(bool NULLEnd = false) const; - - Elf_Sym_iterator begin_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = getDynamicSymbolTableSectionHeader(); - if (DynSymtab) - return Elf_Sym_iterator(DynSymtab->sh_entsize, - (const char *)base() + DynSymtab->sh_offset); - return Elf_Sym_iterator(0, 0); + Elf_Dyn_Iter end_dynamic_table(bool NULLEnd = false) const; + + Elf_Sym_Iter begin_dynamic_symbols() const { + if (DynSymRegion.Addr) + return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr, + true); + return Elf_Sym_Iter(0, 0, true); } - Elf_Sym_iterator end_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = getDynamicSymbolTableSectionHeader(); - if (DynSymtab) - return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + - DynSymtab->sh_offset + DynSymtab->sh_size); - return Elf_Sym_iterator(0, 0); + Elf_Sym_Iter end_dynamic_symbols() const { + if (DynSymRegion.Addr) + return Elf_Sym_Iter(DynSymRegion.EntSize, + (const char *)DynSymRegion.Addr + DynSymRegion.Size, + true); + return Elf_Sym_Iter(0, 0, true); } - Elf_Rela_Iter beginELFRela(const Elf_Shdr *sec) const { + Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const { return Elf_Rela_Iter(sec->sh_entsize, (const char *)(base() + sec->sh_offset)); } - Elf_Rela_Iter endELFRela(const Elf_Shdr *sec) const { - return Elf_Rela_Iter(sec->sh_entsize, (const char *) - (base() + sec->sh_offset + sec->sh_size)); + Elf_Rela_Iter end_rela(const Elf_Shdr *sec) const { + return Elf_Rela_Iter( + sec->sh_entsize, + (const char *)(base() + sec->sh_offset + sec->sh_size)); } - Elf_Rel_Iter beginELFRel(const Elf_Shdr *sec) const { + Elf_Rel_Iter begin_rel(const Elf_Shdr *sec) const { return Elf_Rel_Iter(sec->sh_entsize, (const char *)(base() + sec->sh_offset)); } - Elf_Rel_Iter endELFRel(const Elf_Shdr *sec) const { - return Elf_Rel_Iter(sec->sh_entsize, (const char *) - (base() + sec->sh_offset + sec->sh_size)); + Elf_Rel_Iter end_rel(const Elf_Shdr *sec) const { + return Elf_Rel_Iter(sec->sh_entsize, + (const char *)(base() + sec->sh_offset + sec->sh_size)); } /// \brief Iterate over program header table. @@ -806,43 +387,42 @@ public: (Header->e_phnum * Header->e_phentsize)); } - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual StringRef getObjectType() const { return "ELF"; } - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; - virtual error_code getSectionContents(const Elf_Shdr *sec, - StringRef &Res) const; - uint64_t getNumSections() const; - uint64_t getStringTableIndex() const; + uintX_t getStringTableIndex() const; ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; - const Elf_Ehdr *getElfHeader() const; + const Elf_Ehdr *getHeader() const { return Header; } const Elf_Shdr *getSection(const Elf_Sym *symb) const; - const Elf_Shdr *getElfSection(section_iterator &It) const; - const Elf_Sym *getElfSymbol(symbol_iterator &It) const; - const Elf_Sym *getElfSymbol(uint32_t index) const; - - // Methods for type inquiry through isa, cast, and dyn_cast - bool isDyldType() const { return isDyldELFObject; } - static inline bool classof(const Binary *v) { - return v->getType() == getELFType(ELFT::TargetEndianness == support::little, - ELFT::Is64Bits); - } + const Elf_Shdr *getSection(uint32_t Index) const; + const Elf_Sym *getSymbol(uint32_t index) const; + + ErrorOr<StringRef> getSymbolName(Elf_Sym_Iter Sym) const; + + /// \brief Get the name of \p Symb. + /// \param SymTab The symbol table section \p Symb is contained in. + /// \param Symb The symbol to get the name of. + /// + /// \p SymTab is used to lookup the string table to use to get the symbol's + /// name. + ErrorOr<StringRef> getSymbolName(const Elf_Shdr *SymTab, + const Elf_Sym *Symb) const; + ErrorOr<StringRef> getSectionName(const Elf_Shdr *Section) const; + uint64_t getSymbolIndex(const Elf_Sym *sym) const; + ErrorOr<ArrayRef<uint8_t> > getSectionContents(const Elf_Shdr *Sec) const; + StringRef getLoadName() const; }; // Use an alignment of 2 for the typedefs since that is the worst case for // ELF files in archives. -typedef ELFObjectFile<ELFType<support::little, 2, false> > ELF32LEObjectFile; -typedef ELFObjectFile<ELFType<support::little, 2, true> > ELF64LEObjectFile; -typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile; -typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile; +typedef ELFFile<ELFType<support::little, 2, false> > ELF32LEFile; +typedef ELFFile<ELFType<support::little, 2, true> > ELF64LEFile; +typedef ELFFile<ELFType<support::big, 2, false> > ELF32BEFile; +typedef ELFFile<ELFType<support::big, 2, true> > ELF64BEFile; // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. -template<class ELFT> -void ELFObjectFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { - unsigned vd_size = sec->sh_size; // Size of section in bytes +template <class ELFT> +void ELFFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { + unsigned vd_size = sec->sh_size; // Size of section in bytes unsigned vd_count = sec->sh_info; // Number of Verdef entries const char *sec_start = (const char*)base() + sec->sh_offset; const char *sec_end = sec_start + vd_size; @@ -857,7 +437,7 @@ void ELFObjectFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { report_fatal_error("Unexpected verdef version"); size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; if (index >= VersionMap.size()) - VersionMap.resize(index+1); + VersionMap.resize(index + 1); VersionMap[index] = VersionMapEntry(vd); p += vd->vd_next; } @@ -865,11 +445,11 @@ void ELFObjectFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. -template<class ELFT> -void ELFObjectFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { - unsigned vn_size = sec->sh_size; // Size of section in bytes +template <class ELFT> +void ELFFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { + unsigned vn_size = sec->sh_size; // Size of section in bytes unsigned vn_count = sec->sh_info; // Number of Verneed entries - const char *sec_start = (const char*)base() + sec->sh_offset; + const char *sec_start = (const char *)base() + sec->sh_offset; const char *sec_end = sec_start + vn_size; // The first Verneed entry is at the start of the section. const char *p = sec_start; @@ -889,7 +469,7 @@ void ELFObjectFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux); size_t index = vna->vna_other & ELF::VERSYM_VERSION; if (index >= VersionMap.size()) - VersionMap.resize(index+1); + VersionMap.resize(index + 1); VersionMap[index] = VersionMapEntry(vna); paux += vna->vna_next; } @@ -897,11 +477,10 @@ void ELFObjectFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { } } -template<class ELFT> -void ELFObjectFile<ELFT>::LoadVersionMap() const { +template <class ELFT> +void ELFFile<ELFT>::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (getDynamicStringTableSectionHeader() == NULL || - dot_gnu_version_sec == NULL) + if (DynSymRegion.Addr == NULL || dot_gnu_version_sec == NULL) return; // Has the VersionMap already been loaded? @@ -920,64 +499,16 @@ void ELFObjectFile<ELFT>::LoadVersionMap() const { LoadVersionNeeds(dot_gnu_version_r_sec); } -template<class ELFT> -void ELFObjectFile<ELFT>::validateSymbol(DataRefImpl Symb) const { -#ifndef NDEBUG - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *SymbolTableSection = getSection(Symb.d.b); - // FIXME: We really need to do proper error handling in the case of an invalid - // input file. Because we don't use exceptions, I think we'll just pass - // an error object around. - if (!( symb - && SymbolTableSection - && symb >= (const Elf_Sym*)(base() - + SymbolTableSection->sh_offset) - && symb < (const Elf_Sym*)(base() - + SymbolTableSection->sh_offset - + SymbolTableSection->sh_size))) - // FIXME: Proper error handling. - report_fatal_error("Symb must point to a valid symbol!"); -#endif -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) const { - validateSymbol(Symb); - ++Symb.d.a; - Result = SymbolRef(Symb, this); - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - return getSymbolName(getSection(Symb.d.b), symb, Result); -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { - DataRefImpl Symb = SymRef.getRawDataRefImpl(); - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - return getSymbolVersion(getSection(Symb.d.b), symb, Version, IsDefault); -} - -template<class ELFT> -ELF::Elf64_Word ELFObjectFile<ELFT> - ::getSymbolTableIndex(const Elf_Sym *symb) const { +template <class ELFT> +ELF::Elf64_Word ELFFile<ELFT>::getSymbolTableIndex(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return ExtendedSymbolTable.lookup(symb); return symb->st_shndx; } -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Shdr * -ELFObjectFile<ELFT>::getSection(const Elf_Sym *symb) const { +template <class ELFT> +const typename ELFFile<ELFT>::Elf_Shdr * +ELFFile<ELFT>::getSection(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); if (symb->st_shndx >= ELF::SHN_LORESERVE) @@ -985,1282 +516,36 @@ ELFObjectFile<ELFT>::getSection(const Elf_Sym *symb) const { return getSection(symb->st_shndx); } -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Ehdr * -ELFObjectFile<ELFT>::getElfHeader() const { - return Header; -} - -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Shdr * -ELFObjectFile<ELFT>::getElfSection(section_iterator &It) const { - llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); - return reinterpret_cast<const Elf_Shdr *>(ShdrRef.p); -} - -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Sym * -ELFObjectFile<ELFT>::getElfSymbol(symbol_iterator &It) const { - return getSymbol(It->getRawDataRefImpl()); -} - -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Sym * -ELFObjectFile<ELFT>::getElfSymbol(uint32_t index) const { - DataRefImpl SymbolData; - SymbolData.d.a = index; - SymbolData.d.b = SymbolTableIndex; - return getSymbol(SymbolData); -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_COMMON: - // Unintialized symbols have no offset in the object file - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = symb->st_value; - return object_error::success; - default: Section = getSection(symb); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: - Result = Section ? Section->sh_offset : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - Result = symb->st_value + - (Section ? Section->sh_offset : 0); - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_COMMON: - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = symb->st_value; - return object_error::success; - default: Section = getSection(symb); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: - Result = Section ? Section->sh_addr : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - bool IsRelocatable; - switch(Header->e_type) { - case ELF::ET_EXEC: - case ELF::ET_DYN: - IsRelocatable = false; - break; - default: - IsRelocatable = true; - } - Result = symb->st_value; - - // Clear the ARM/Thumb indicator flag. - if (Header->e_machine == ELF::EM_ARM) - Result &= ~1; - - if (IsRelocatable && Section != 0) - Result += Section->sh_addr; - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const { - uint32_t flags; - getSymbolFlags(Symb, flags); - if (flags & SymbolRef::SF_Common) { - uint64_t Value; - getSymbolValue(Symb, Value); - Res = Value; - } else { - Res = 0; - } - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - if (symb->st_size == 0) - Result = UnknownAddressOrSize; - Result = symb->st_size; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolNMTypeChar(DataRefImpl Symb, - char &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section = getSection(symb); - - char ret = '?'; - - if (Section) { - switch (Section->sh_type) { - case ELF::SHT_PROGBITS: - case ELF::SHT_DYNAMIC: - switch (Section->sh_flags) { - case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): - ret = 't'; break; - case (ELF::SHF_ALLOC | ELF::SHF_WRITE): - ret = 'd'; break; - case ELF::SHF_ALLOC: - case (ELF::SHF_ALLOC | ELF::SHF_MERGE): - case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): - ret = 'r'; break; - } - break; - case ELF::SHT_NOBITS: ret = 'b'; - } - } - - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_UNDEF: - if (ret == '?') - ret = 'U'; - break; - case ELF::SHN_ABS: ret = 'a'; break; - case ELF::SHN_COMMON: ret = 'c'; break; - } - - switch (symb->getBinding()) { - case ELF::STB_GLOBAL: ret = ::toupper(ret); break; - case ELF::STB_WEAK: - if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) - ret = 'w'; - else - if (symb->getType() == ELF::STT_OBJECT) - ret = 'V'; - else - ret = 'W'; - } - - if (ret == '?' && symb->getType() == ELF::STT_SECTION) { - StringRef name; - if (error_code ec = getSymbolName(Symb, name)) - return ec; - Result = StringSwitch<char>(name) - .StartsWith(".debug", 'N') - .StartsWith(".note", 'n') - .Default('?'); - return object_error::success; - } - - Result = ret; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - switch (symb->getType()) { - case ELF::STT_NOTYPE: - Result = SymbolRef::ST_Unknown; - break; - case ELF::STT_SECTION: - Result = SymbolRef::ST_Debug; - break; - case ELF::STT_FILE: - Result = SymbolRef::ST_File; - break; - case ELF::STT_FUNC: - Result = SymbolRef::ST_Function; - break; - case ELF::STT_OBJECT: - case ELF::STT_COMMON: - case ELF::STT_TLS: - Result = SymbolRef::ST_Data; - break; - default: - Result = SymbolRef::ST_Other; - break; - } - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - Result = SymbolRef::SF_None; - - if (symb->getBinding() != ELF::STB_LOCAL) - Result |= SymbolRef::SF_Global; - - if (symb->getBinding() == ELF::STB_WEAK) - Result |= SymbolRef::SF_Weak; - - if (symb->st_shndx == ELF::SHN_ABS) - Result |= SymbolRef::SF_Absolute; - - if (symb->getType() == ELF::STT_FILE || - symb->getType() == ELF::STT_SECTION || - Symb == begin_symbols()->getRawDataRefImpl()) - Result |= SymbolRef::SF_FormatSpecific; - - if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) - Result |= SymbolRef::SF_Undefined; - - if (symb->getType() == ELF::STT_COMMON || - getSymbolTableIndex(symb) == ELF::SHN_COMMON) - Result |= SymbolRef::SF_Common; - - if (symb->getType() == ELF::STT_TLS) - Result |= SymbolRef::SF_ThreadLocal; - - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *sec = getSection(symb); - if (!sec) - Res = end_sections(); - else { - DataRefImpl Sec; - Sec.p = reinterpret_cast<intptr_t>(sec); - Res = section_iterator(SectionRef(Sec, this)); - } - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - Val = symb->st_value; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSectionNext(DataRefImpl Sec, - SectionRef &Result) const { - const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); - sec += Header->e_shentsize; - Sec.p = reinterpret_cast<intptr_t>(sec); - Result = SectionRef(Sec, this); - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, - StringRef &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - Result = sec->sh_addr; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - Result = sec->sh_size; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - const char *start = (const char*)base() + sec->sh_offset; - Result = StringRef(start, sec->sh_size); - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSectionContents(const Elf_Shdr *Sec, - StringRef &Result) const { - const char *start = (const char*)base() + Sec->sh_offset; - Result = StringRef(start, Sec->sh_size); - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - Result = sec->sh_addralign; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - if (sec->sh_flags & ELF::SHF_EXECINSTR) - Result = true; - else - Result = false; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) - && sec->sh_type == ELF::SHT_PROGBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) - && sec->sh_type == ELF::SHT_NOBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::isSectionRequiredForExecution( - DataRefImpl Sec, bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - if (sec->sh_flags & ELF::SHF_ALLOC) - Result = true; - else - Result = false; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - if (sec->sh_type == ELF::SHT_NOBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - // For ELF, all zero-init sections are virtual (that is, they occupy no space - // in the object image) and vice versa. - Result = sec->sh_type == ELF::SHT_NOBITS; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - if (sec->sh_flags & ELF::SHF_WRITE || sec->sh_flags & ELF::SHF_EXECINSTR) - Result = false; - else - Result = true; - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { - validateSymbol(Symb); - - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - const Elf_Sym *symb = getSymbol(Symb); - - unsigned shndx = symb->st_shndx; - bool Reserved = shndx >= ELF::SHN_LORESERVE - && shndx <= ELF::SHN_HIRESERVE; - - Result = !Reserved && (sec == getSection(symb->st_shndx)); - return object_error::success; -} - -template<class ELFT> -relocation_iterator -ELFObjectFile<ELFT>::getSectionRelBegin(DataRefImpl Sec) const { - DataRefImpl RelData; - uintptr_t SHT = reinterpret_cast<uintptr_t>(SectionHeaderTable); - RelData.d.a = (Sec.p - SHT) / Header->e_shentsize; - RelData.d.b = 0; - return relocation_iterator(RelocationRef(RelData, this)); -} - -template<class ELFT> -relocation_iterator -ELFObjectFile<ELFT>::getSectionRelEnd(DataRefImpl Sec) const { - DataRefImpl RelData; - uintptr_t SHT = reinterpret_cast<uintptr_t>(SectionHeaderTable); - const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); - RelData.d.a = (Sec.p - SHT) / Header->e_shentsize; - if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) - RelData.d.b = 0; - else - RelData.d.b = S->sh_size / S->sh_entsize; - - return relocation_iterator(RelocationRef(RelData, this)); -} - template <class ELFT> -section_iterator -ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { - if (Header->e_type != ELF::ET_REL) - return end_sections(); - - const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); - unsigned sh_type = S->sh_type; - if (sh_type != ELF::SHT_RELA && sh_type != ELF::SHT_REL) - return end_sections(); - - assert(S->sh_info != 0); - const Elf_Shdr *R = getSection(S->sh_info); - DataRefImpl D; - D.p = reinterpret_cast<uintptr_t>(R); - return section_iterator(SectionRef(D, this)); -} - -// Relocations -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { - ++Rel.d.b; - Result = RelocationRef(Rel, this); - return object_error::success; +const typename ELFFile<ELFT>::Elf_Sym * +ELFFile<ELFT>::getSymbol(uint32_t Index) const { + return &*(begin_symbols() + Index); } template <class ELFT> -symbol_iterator -ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { - uint32_t symbolIdx; - const Elf_Shdr *sec = getRelSection(Rel); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - symbolIdx = getRel(Rel)->getSymbol(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - symbolIdx = getRela(Rel)->getSymbol(isMips64EL()); - break; - } - } - if (!symbolIdx) - return end_symbols(); - - DataRefImpl SymbolData; - SymbolData.d.a = symbolIdx; - SymbolData.d.b = sec->sh_link; - return symbol_iterator(SymbolRef(SymbolData, this)); -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { - assert((Header->e_type == ELF::ET_EXEC || Header->e_type == ELF::ET_DYN) && - "Only executable and shared objects files have addresses"); - Result = getROffset(Rel); - return object_error::success; +ErrorOr<ArrayRef<uint8_t> > +ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { + if (Sec->sh_offset + Sec->sh_size > Buf->getBufferSize()) + return object_error::parse_failed; + const uint8_t *Start = base() + Sec->sh_offset; + return ArrayRef<uint8_t>(Start, Sec->sh_size); } -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { - assert(Header->e_type == ELF::ET_REL && - "Only relocatable object files have relocation offsets"); - Result = getROffset(Rel); - return object_error::success; -} - -template<class ELFT> -uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { - const Elf_Shdr *sec = getRelSection(Rel); - switch (sec->sh_type) { - default: - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL: - return getRel(Rel)->r_offset; - case ELF::SHT_RELA: - return getRela(Rel)->r_offset; - } -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { - const Elf_Shdr *sec = getRelSection(Rel); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - Result = getRel(Rel)->getType(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - Result = getRela(Rel)->getType(isMips64EL()); - break; - } - } - return object_error::success; -} - -#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ - case ELF::enum: Res = #enum; break; - -template<class ELFT> -StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { - StringRef Res = "Unknown"; - switch (Header->e_machine) { - case ELF::EM_X86_64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); - default: break; - } - break; - case ELF::EM_386: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); - default: break; - } - break; - case ELF::EM_MIPS: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LITERAL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_UNUSED1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_UNUSED2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_OFST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SUB); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_A); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_B); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_DELETE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SCN_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_ADD_IMMEDIATE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PJUMP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_RELGOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JALR); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GOTTPREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NUM); - default: break; - } - break; - case ELF::EM_AARCH64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD_PREL_LO19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_LO21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_PG_HI21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADD_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST8_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TSTBR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CONDBR19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_JUMP26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CALL26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST16_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST32_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST64_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST128_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD64_GOT_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_HI12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_HI12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADR_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); - default: break; - } - break; - case ELF::EM_ARM: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PC24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ABS5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BREL_ADJ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_SWI8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_XPC25); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_XPC22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_7_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_15_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_23_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SBREL_11_0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_19_12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_27_20_CK); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_V4BX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ALU_PREL_11_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESCSEQ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTRELAX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTENTRY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTINHERIT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE12GP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_4); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_7); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_9); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_13); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ME_TOO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ32); - default: break; - } - break; - case ELF::EM_HEXAGON: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B32_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_12_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_10_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_9_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_7_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPMOD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); - default: break; - } - break; - case ELF::EM_PPC: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HA); - default: break; - } - break; - case ELF::EM_PPC64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHERA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHESTA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHERA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHESTA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHERA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHESTA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HA); - default: break; - } - break; - case ELF::EM_S390: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT16DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPCDBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLTENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LOAD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GDCALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDCALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IEENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPMOD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_IRELATIVE); - default: break; - } - break; - default: break; - } - return Res; +template <class ELFT> +StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { + return getELFRelocationTypeName(Header->e_machine, Type); } -#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationTypeName( - DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const Elf_Shdr *sec = getRelSection(Rel); - uint32_t type; - switch (sec->sh_type) { - default : - return object_error::parse_failed; - case ELF::SHT_REL : { - type = getRel(Rel)->getType(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - type = getRela(Rel)->getType(isMips64EL()); - break; - } - } - +template <class ELFT> +void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, + SmallVectorImpl<char> &Result) const { if (!isMips64EL()) { - StringRef Name = getRelocationTypeName(type); + StringRef Name = getRelocationTypeName(Type); Result.append(Name.begin(), Name.end()); } else { - uint8_t Type1 = (type >> 0) & 0xFF; - uint8_t Type2 = (type >> 8) & 0xFF; - uint8_t Type3 = (type >> 16) & 0xFF; + uint8_t Type1 = (Type >> 0) & 0xFF; + uint8_t Type2 = (Type >> 8) & 0xFF; + uint8_t Type3 = (Type >> 16) & 0xFF; // Concat all three relocation type names. StringRef Name = getRelocationTypeName(Type1); @@ -2274,135 +559,63 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( Result.append(1, '/'); Result.append(Name.begin(), Name.end()); } - - return object_error::success; } -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationAddend( - DataRefImpl Rel, int64_t &Result) const { - const Elf_Shdr *sec = getRelSection(Rel); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - Result = 0; - return object_error::success; - } - case ELF::SHT_RELA : { - Result = getRela(Rel)->r_addend; - return object_error::success; - } - } -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationValueString( - DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const Elf_Shdr *sec = getRelSection(Rel); - uint8_t type; - StringRef res; - int64_t addend = 0; - uint16_t symbol_index = 0; - switch (sec->sh_type) { - default: - return object_error::parse_failed; - case ELF::SHT_REL: { - type = getRel(Rel)->getType(isMips64EL()); - symbol_index = getRel(Rel)->getSymbol(isMips64EL()); - // TODO: Read implicit addend from section data. - break; - } - case ELF::SHT_RELA: { - type = getRela(Rel)->getType(isMips64EL()); - symbol_index = getRela(Rel)->getSymbol(isMips64EL()); - addend = getRela(Rel)->r_addend; - break; - } - } - const Elf_Sym *symb = getEntry<Elf_Sym>(sec->sh_link, symbol_index); - StringRef symname; - if (error_code ec = getSymbolName(getSection(sec->sh_link), symb, symname)) - return ec; - switch (Header->e_machine) { - case ELF::EM_X86_64: - switch (type) { - case ELF::R_X86_64_PC8: - case ELF::R_X86_64_PC16: - case ELF::R_X86_64_PC32: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname << (addend < 0 ? "" : "+") << addend << "-P"; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } - break; - case ELF::R_X86_64_8: - case ELF::R_X86_64_16: - case ELF::R_X86_64_32: - case ELF::R_X86_64_32S: - case ELF::R_X86_64_64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } - break; - default: - res = "Unknown"; - } - break; - case ELF::EM_AARCH64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname; - if (addend != 0) - fmt << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - break; - } - case ELF::EM_ARM: - case ELF::EM_HEXAGON: - res = symname; - break; - default: - res = "Unknown"; - } - if (Result.empty()) - Result.append(res.begin(), res.end()); - return object_error::success; +template <class ELFT> +template <class RelT> +std::pair<const typename ELFFile<ELFT>::Elf_Shdr *, + const typename ELFFile<ELFT>::Elf_Sym *> +ELFFile<ELFT>::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { + if (!Sec->sh_link) + return std::make_pair((const Elf_Shdr *)0, (const Elf_Sym *)0); + const Elf_Shdr *SymTable = getSection(Sec->sh_link); + return std::make_pair( + SymTable, getEntry<Elf_Sym>(SymTable, Rel->getSymbol(isMips64EL()))); } // Verify that the last byte in the string table in a null. -template<class ELFT> -void ELFObjectFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const { - const char *strtab = (const char*)base() + sh->sh_offset; +template <class ELFT> +void ELFFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const { + const char *strtab = (const char *)base() + sh->sh_offset; if (strtab[sh->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); } -template<class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(getELFType( - static_cast<endianness>(ELFT::TargetEndianness) == support::little, - ELFT::Is64Bits), - Object) - , isDyldELFObject(false) - , SectionHeaderTable(0) - , dot_shstrtab_sec(0) - , dot_strtab_sec(0) - , dot_dynstr_sec(0) - , dot_dynamic_sec(0) - , dot_gnu_version_sec(0) - , dot_gnu_version_r_sec(0) - , dot_gnu_version_d_sec(0) - , dt_soname(0) - { - - const uint64_t FileSize = Data->getBufferSize(); +template <class ELFT> +uint64_t ELFFile<ELFT>::getNumSections() const { + assert(Header && "Header not initialized!"); + if (Header->e_shnum == ELF::SHN_UNDEF) { + assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); + return SectionHeaderTable->sh_size; + } + return Header->e_shnum; +} + +template <class ELFT> +typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const { + if (Header->e_shnum == ELF::SHN_UNDEF) { + if (Header->e_shstrndx == ELF::SHN_HIRESERVE) + return SectionHeaderTable->sh_link; + if (Header->e_shstrndx >= getNumSections()) + return 0; + } + return Header->e_shstrndx; +} + +template <class ELFT> +ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec) + : Buf(Object), + SectionHeaderTable(0), + dot_shstrtab_sec(0), + dot_strtab_sec(0), + dot_symtab_sec(0), + SymbolTableSectionHeaderIndex(0), + dot_gnu_version_sec(0), + dot_gnu_version_r_sec(0), + dot_gnu_version_d_sec(0), + dt_soname(0) { + const uint64_t FileSize = Buf->getBufferSize(); if (sizeof(Elf_Ehdr) > FileSize) // FIXME: Proper error handling. @@ -2428,68 +641,64 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) // FIXME: Proper error handling. report_fatal_error("Section table goes past end of file!"); - // To find the symbol tables we walk the section table to find SHT_SYMTAB. - const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; - const Elf_Shdr* sh = SectionHeaderTable; + // Scan sections for special sections. - SymbolTableIndex = -1; - DynamicSymbolTableIndex = -1; - - for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { - switch (sh->sh_type) { - case ELF::SHT_SYMTAB_SHNDX: { + for (Elf_Shdr_Iter SecI = begin_sections(), SecE = end_sections(); + SecI != SecE; ++SecI) { + switch (SecI->sh_type) { + case ELF::SHT_SYMTAB_SHNDX: if (SymbolTableSectionHeaderIndex) // FIXME: Proper error handling. report_fatal_error("More than one .symtab_shndx!"); - SymbolTableSectionHeaderIndex = sh; + SymbolTableSectionHeaderIndex = &*SecI; break; - } - case ELF::SHT_SYMTAB: { - if (SymbolTableIndex != -1) - report_fatal_error("More than one SHT_SYMTAB!"); - SymbolTableIndex = i; + case ELF::SHT_SYMTAB: + if (dot_symtab_sec) + // FIXME: Proper error handling. + report_fatal_error("More than one .symtab!"); + dot_symtab_sec = &*SecI; + dot_strtab_sec = getSection(SecI->sh_link); break; - } case ELF::SHT_DYNSYM: { - if (DynamicSymbolTableIndex != -1) + if (DynSymRegion.Addr) // FIXME: Proper error handling. - report_fatal_error("More than one SHT_DYNSYM!"); - DynamicSymbolTableIndex = i; + report_fatal_error("More than one .dynsym!"); + DynSymRegion.Addr = base() + SecI->sh_offset; + DynSymRegion.Size = SecI->sh_size; + DynSymRegion.EntSize = SecI->sh_entsize; + const Elf_Shdr *DynStr = getSection(SecI->sh_link); + DynStrRegion.Addr = base() + DynStr->sh_offset; + DynStrRegion.Size = DynStr->sh_size; + DynStrRegion.EntSize = DynStr->sh_entsize; break; } - case ELF::SHT_REL: - case ELF::SHT_RELA: - break; - case ELF::SHT_DYNAMIC: { - if (dot_dynamic_sec != NULL) + case ELF::SHT_DYNAMIC: + if (DynamicRegion.Addr) // FIXME: Proper error handling. report_fatal_error("More than one .dynamic!"); - dot_dynamic_sec = sh; + DynamicRegion.Addr = base() + SecI->sh_offset; + DynamicRegion.Size = SecI->sh_size; + DynamicRegion.EntSize = SecI->sh_entsize; break; - } - case ELF::SHT_GNU_versym: { + case ELF::SHT_GNU_versym: if (dot_gnu_version_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version section!"); - dot_gnu_version_sec = sh; + dot_gnu_version_sec = &*SecI; break; - } - case ELF::SHT_GNU_verdef: { + case ELF::SHT_GNU_verdef: if (dot_gnu_version_d_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_d section!"); - dot_gnu_version_d_sec = sh; + dot_gnu_version_d_sec = &*SecI; break; - } - case ELF::SHT_GNU_verneed: { + case ELF::SHT_GNU_verneed: if (dot_gnu_version_r_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_r section!"); - dot_gnu_version_r_sec = sh; + dot_gnu_version_r_sec = &*SecI; break; } - } - ++sh; } // Get string table sections. @@ -2499,173 +708,117 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) VerifyStrTab(dot_shstrtab_sec); } - // Merge this into the above loop. - for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), - *e = i + getNumSections() * Header->e_shentsize; - i != e; i += Header->e_shentsize) { - const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); - if (sh->sh_type == ELF::SHT_STRTAB) { - StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); - if (SectionName == ".strtab") { - if (dot_strtab_sec != 0) - // FIXME: Proper error handling. - report_fatal_error("Already found section named .strtab!"); - dot_strtab_sec = sh; - VerifyStrTab(dot_strtab_sec); - } else if (SectionName == ".dynstr") { - if (dot_dynstr_sec != 0) - // FIXME: Proper error handling. - report_fatal_error("Already found section named .dynstr!"); - dot_dynstr_sec = sh; - VerifyStrTab(dot_dynstr_sec); - } - } - } - // Build symbol name side-mapping if there is one. if (SymbolTableSectionHeaderIndex) { const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word*>(base() + SymbolTableSectionHeaderIndex->sh_offset); - error_code ec; - for (symbol_iterator si = begin_symbols(), - se = end_symbols(); si != se; si.increment(ec)) { - if (ec) - report_fatal_error("Fewer extended symbol table entries than symbols!"); + for (Elf_Sym_Iter SI = begin_symbols(), SE = end_symbols(); SI != SE; + ++SI) { if (*ShndxTable != ELF::SHN_UNDEF) - ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable; + ExtendedSymbolTable[&*SI] = *ShndxTable; ++ShndxTable; } } + + // Scan program headers. + for (Elf_Phdr_Iter PhdrI = begin_program_headers(), + PhdrE = end_program_headers(); + PhdrI != PhdrE; ++PhdrI) { + if (PhdrI->p_type == ELF::PT_DYNAMIC) { + DynamicRegion.Addr = base() + PhdrI->p_offset; + DynamicRegion.Size = PhdrI->p_filesz; + DynamicRegion.EntSize = sizeof(Elf_Dyn); + break; + } + } + + ec = error_code::success(); } // Get the symbol table index in the symtab section given a symbol -template<class ELFT> -uint64_t ELFObjectFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { - const Elf_Shdr *SymTab = getSection(SymbolTableIndex); +template <class ELFT> +uint64_t ELFFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { uintptr_t SymLoc = uintptr_t(Sym); - uintptr_t SymTabLoc = uintptr_t(base() + SymTab->sh_offset); + uintptr_t SymTabLoc = uintptr_t(base() + dot_symtab_sec->sh_offset); assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); uint64_t SymOffset = SymLoc - SymTabLoc; - assert(SymOffset % SymTab->sh_entsize == 0 && + assert(SymOffset % dot_symtab_sec->sh_entsize == 0 && "Symbol not multiple of symbol size!"); - return SymOffset / SymTab->sh_entsize; + return SymOffset / dot_symtab_sec->sh_entsize; } -template<class ELFT> -symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { - DataRefImpl SymbolData; - if (SymbolTableIndex == -1) { - SymbolData.d.a = 0; - SymbolData.d.b = 0; - } else { - SymbolData.d.a = 0; - SymbolData.d.b = SymbolTableIndex; - } - return symbol_iterator(SymbolRef(SymbolData, this)); +template <class ELFT> +typename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::begin_sections() const { + return Elf_Shdr_Iter(Header->e_shentsize, + (const char *)base() + Header->e_shoff); } -template<class ELFT> -symbol_iterator ELFObjectFile<ELFT>::end_symbols() const { - DataRefImpl SymbolData; - if (SymbolTableIndex == -1) { - SymbolData.d.a = 0; - SymbolData.d.b = 0; - } else { - const Elf_Shdr *SymbolTableSection = getSection(SymbolTableIndex); - SymbolData.d.a = SymbolTableSection->getEntityCount(); - SymbolData.d.b = SymbolTableIndex; - } - return symbol_iterator(SymbolRef(SymbolData, this)); +template <class ELFT> +typename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::end_sections() const { + return Elf_Shdr_Iter(Header->e_shentsize, + (const char *)base() + Header->e_shoff + + (getNumSections() * Header->e_shentsize)); } -template<class ELFT> -symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { - DataRefImpl SymbolData; - if (DynamicSymbolTableIndex == -1) { - SymbolData.d.a = 0; - SymbolData.d.b = 0; - } else { - SymbolData.d.a = 0; - SymbolData.d.b = DynamicSymbolTableIndex; - } - return symbol_iterator(SymbolRef(SymbolData, this)); +template <class ELFT> +typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const { + if (!dot_symtab_sec) + return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, + (const char *)base() + dot_symtab_sec->sh_offset, false); } -template<class ELFT> -symbol_iterator ELFObjectFile<ELFT>::end_dynamic_symbols() const { - DataRefImpl SymbolData; - if (DynamicSymbolTableIndex == -1) { - SymbolData.d.a = 0; - SymbolData.d.b = 0; - } else { - const Elf_Shdr *SymbolTableSection = getSection(DynamicSymbolTableIndex); - SymbolData.d.a = SymbolTableSection->getEntityCount(); - SymbolData.d.b = DynamicSymbolTableIndex; - } - return symbol_iterator(SymbolRef(SymbolData, this)); +template <class ELFT> +typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::end_symbols() const { + if (!dot_symtab_sec) + return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, + (const char *)base() + dot_symtab_sec->sh_offset + + dot_symtab_sec->sh_size, + false); } -template<class ELFT> -section_iterator ELFObjectFile<ELFT>::begin_sections() const { - DataRefImpl ret; - ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); - return section_iterator(SectionRef(ret, this)); +template <class ELFT> +typename ELFFile<ELFT>::Elf_Dyn_Iter +ELFFile<ELFT>::begin_dynamic_table() const { + if (DynamicRegion.Addr) + return Elf_Dyn_Iter(DynamicRegion.EntSize, + (const char *)DynamicRegion.Addr); + return Elf_Dyn_Iter(0, 0); } -template<class ELFT> -section_iterator ELFObjectFile<ELFT>::end_sections() const { - DataRefImpl ret; - ret.p = reinterpret_cast<intptr_t>(base() - + Header->e_shoff - + (Header->e_shentsize*getNumSections())); - return section_iterator(SectionRef(ret, this)); -} +template <class ELFT> +typename ELFFile<ELFT>::Elf_Dyn_Iter +ELFFile<ELFT>::end_dynamic_table(bool NULLEnd) const { + if (!DynamicRegion.Addr) + return Elf_Dyn_Iter(0, 0); + Elf_Dyn_Iter Ret(DynamicRegion.EntSize, + (const char *)DynamicRegion.Addr + DynamicRegion.Size); -template<class ELFT> -typename ELFObjectFile<ELFT>::Elf_Dyn_iterator -ELFObjectFile<ELFT>::begin_dynamic_table() const { - if (dot_dynamic_sec) - return Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - (const char *)base() + dot_dynamic_sec->sh_offset); - return Elf_Dyn_iterator(0, 0); -} + if (NULLEnd) { + Elf_Dyn_Iter Start = begin_dynamic_table(); + while (Start != Ret && Start->getTag() != ELF::DT_NULL) + ++Start; -template<class ELFT> -typename ELFObjectFile<ELFT>::Elf_Dyn_iterator -ELFObjectFile<ELFT>::end_dynamic_table(bool NULLEnd) const { - if (dot_dynamic_sec) { - Elf_Dyn_iterator Ret(dot_dynamic_sec->sh_entsize, - (const char *)base() + dot_dynamic_sec->sh_offset + - dot_dynamic_sec->sh_size); - - if (NULLEnd) { - Elf_Dyn_iterator Start = begin_dynamic_table(); - while (Start != Ret && Start->getTag() != ELF::DT_NULL) - ++Start; - - // Include the DT_NULL. - if (Start != Ret) - ++Start; - Ret = Start; - } - return Ret; + // Include the DT_NULL. + if (Start != Ret) + ++Start; + Ret = Start; } - return Elf_Dyn_iterator(0, 0); + return Ret; } -template<class ELFT> -StringRef ELFObjectFile<ELFT>::getLoadName() const { +template <class ELFT> +StringRef ELFFile<ELFT>::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry - Elf_Dyn_iterator it = begin_dynamic_table(); - Elf_Dyn_iterator ie = end_dynamic_table(); + Elf_Dyn_Iter it = begin_dynamic_table(); + Elf_Dyn_Iter ie = end_dynamic_table(); while (it != ie && it->getTag() != ELF::DT_SONAME) ++it; if (it != ie) { - if (dot_dynstr_sec == NULL) - report_fatal_error("Dynamic string table is missing"); - dt_soname = getString(dot_dynstr_sec, it->getVal()); + dt_soname = getDynamicString(it->getVal()); } else { dt_soname = ""; } @@ -2673,210 +826,23 @@ StringRef ELFObjectFile<ELFT>::getLoadName() const { return dt_soname; } -template<class ELFT> -library_iterator ELFObjectFile<ELFT>::begin_libraries_needed() const { - // Find the first DT_NEEDED entry - Elf_Dyn_iterator i = begin_dynamic_table(); - Elf_Dyn_iterator e = end_dynamic_table(); - while (i != e && i->getTag() != ELF::DT_NEEDED) - ++i; - - DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(i.get()); - return library_iterator(LibraryRef(DRI, this)); -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { - // Use the same DataRefImpl format as DynRef. - Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - reinterpret_cast<const char *>(Data.p)); - Elf_Dyn_iterator e = end_dynamic_table(); - - // Skip the current dynamic table entry and find the next DT_NEEDED entry. - do - ++i; - while (i != e && i->getTag() != ELF::DT_NEEDED); - - DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(i.get()); - Result = LibraryRef(DRI, this); - return object_error::success; -} - -template<class ELFT> -error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, - StringRef &Res) const { - Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - reinterpret_cast<const char *>(Data.p)); - if (i == end_dynamic_table()) - report_fatal_error("getLibraryPath() called on iterator end"); - - if (i->getTag() != ELF::DT_NEEDED) - report_fatal_error("Invalid library_iterator"); - - // This uses .dynstr to lookup the name of the DT_NEEDED entry. - // THis works as long as DT_STRTAB == .dynstr. This is true most of - // the time, but the specification allows exceptions. - // TODO: This should really use DT_STRTAB instead. Doing this requires - // reading the program headers. - if (dot_dynstr_sec == NULL) - report_fatal_error("Dynamic string table is missing"); - Res = getString(dot_dynstr_sec, i->getVal()); - return object_error::success; -} - -template<class ELFT> -library_iterator ELFObjectFile<ELFT>::end_libraries_needed() const { - Elf_Dyn_iterator e = end_dynamic_table(); - DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(e.get()); - return library_iterator(LibraryRef(DRI, this)); -} - -template<class ELFT> -uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { - return ELFT::Is64Bits ? 8 : 4; -} - -template<class ELFT> -StringRef ELFObjectFile<ELFT>::getFileFormatName() const { - switch(Header->e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: - switch(Header->e_machine) { - case ELF::EM_386: - return "ELF32-i386"; - case ELF::EM_X86_64: - return "ELF32-x86-64"; - case ELF::EM_ARM: - return "ELF32-arm"; - case ELF::EM_HEXAGON: - return "ELF32-hexagon"; - case ELF::EM_MIPS: - return "ELF32-mips"; - case ELF::EM_PPC: - return "ELF32-ppc"; - default: - return "ELF32-unknown"; - } - case ELF::ELFCLASS64: - switch(Header->e_machine) { - case ELF::EM_386: - return "ELF64-i386"; - case ELF::EM_X86_64: - return "ELF64-x86-64"; - case ELF::EM_AARCH64: - return "ELF64-aarch64"; - case ELF::EM_PPC64: - return "ELF64-ppc64"; - case ELF::EM_S390: - return "ELF64-s390"; - default: - return "ELF64-unknown"; - } - default: - // FIXME: Proper error handling. - report_fatal_error("Invalid ELFCLASS!"); - } -} - -template<class ELFT> -unsigned ELFObjectFile<ELFT>::getArch() const { - switch(Header->e_machine) { - case ELF::EM_386: - return Triple::x86; - case ELF::EM_X86_64: - return Triple::x86_64; - case ELF::EM_AARCH64: - return Triple::aarch64; - case ELF::EM_ARM: - return Triple::arm; - case ELF::EM_HEXAGON: - return Triple::hexagon; - case ELF::EM_MIPS: - return (ELFT::TargetEndianness == support::little) ? - Triple::mipsel : Triple::mips; - case ELF::EM_PPC64: - return (ELFT::TargetEndianness == support::little) ? - Triple::ppc64le : Triple::ppc64; - case ELF::EM_S390: - return Triple::systemz; - default: - return Triple::UnknownArch; - } -} - -template<class ELFT> -uint64_t ELFObjectFile<ELFT>::getNumSections() const { - assert(Header && "Header not initialized!"); - if (Header->e_shnum == ELF::SHN_UNDEF) { - assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); - return SectionHeaderTable->sh_size; - } - return Header->e_shnum; -} - -template<class ELFT> -uint64_t -ELFObjectFile<ELFT>::getStringTableIndex() const { - if (Header->e_shnum == ELF::SHN_UNDEF) { - if (Header->e_shstrndx == ELF::SHN_HIRESERVE) - return SectionHeaderTable->sh_link; - if (Header->e_shstrndx >= getNumSections()) - return 0; - } - return Header->e_shstrndx; -} - -template<class ELFT> -template<typename T> -inline const T * -ELFObjectFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const { +template <class ELFT> +template <typename T> +const T *ELFFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const { return getEntry<T>(getSection(Section), Entry); } -template<class ELFT> -template<typename T> -inline const T * -ELFObjectFile<ELFT>::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { - return reinterpret_cast<const T *>( - base() - + Section->sh_offset - + (Entry * Section->sh_entsize)); -} - -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Sym * -ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const { - return getEntry<Elf_Sym>(Symb.d.b, Symb.d.a); -} - -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Rel * -ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { - return getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); -} - -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Rela * -ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { - return getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); -} - -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Shdr * -ELFObjectFile<ELFT>::getSection(DataRefImpl Symb) const { - const Elf_Shdr *sec = getSection(Symb.d.b); - if (sec->sh_type != ELF::SHT_SYMTAB || sec->sh_type != ELF::SHT_DYNSYM) - // FIXME: Proper error handling. - report_fatal_error("Invalid symbol table section!"); - return sec; +template <class ELFT> +template <typename T> +const T *ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, + uint32_t Entry) const { + return reinterpret_cast<const T *>(base() + Section->sh_offset + + (Entry * Section->sh_entsize)); } -template<class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Shdr * -ELFObjectFile<ELFT>::getSection(uint32_t index) const { +template <class ELFT> +const typename ELFFile<ELFT>::Elf_Shdr * +ELFFile<ELFT>::getSection(uint32_t index) const { if (index == 0) return 0; if (!SectionHeaderTable || index >= getNumSections()) @@ -2888,15 +854,15 @@ ELFObjectFile<ELFT>::getSection(uint32_t index) const { + (index * Header->e_shentsize)); } -template<class ELFT> -const char *ELFObjectFile<ELFT>::getString(uint32_t section, - ELF::Elf32_Word offset) const { +template <class ELFT> +const char *ELFFile<ELFT>::getString(uint32_t section, + ELF::Elf32_Word offset) const { return getString(getSection(section), offset); } -template<class ELFT> -const char *ELFObjectFile<ELFT>::getString(const Elf_Shdr *section, - ELF::Elf32_Word offset) const { +template <class ELFT> +const char *ELFFile<ELFT>::getString(const Elf_Shdr *section, + ELF::Elf32_Word offset) const { assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); if (offset >= section->sh_size) // FIXME: Proper error handling. @@ -2904,56 +870,63 @@ const char *ELFObjectFile<ELFT>::getString(const Elf_Shdr *section, return (const char *)base() + section->sh_offset + offset; } -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolName(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Result) const { - if (symb->st_name == 0) { - const Elf_Shdr *section = getSection(symb); - if (!section) - Result = ""; - else - Result = getString(dot_shstrtab_sec, section->sh_name); - return object_error::success; - } +template <class ELFT> +const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const { + if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size) + return 0; + return (const char *)DynStrRegion.Addr + Offset; +} - if (DynamicSymbolTableIndex != -1 && - section == getSection(DynamicSymbolTableIndex)) { - // Symbol is in .dynsym, use .dynstr string table - Result = getString(dot_dynstr_sec, symb->st_name); - } else { - // Use the default symbol table name section. - Result = getString(dot_strtab_sec, symb->st_name); +template <class ELFT> +ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(Elf_Sym_Iter Sym) const { + if (!Sym.isDynamic()) + return getSymbolName(dot_symtab_sec, &*Sym); + + if (!DynStrRegion.Addr || Sym->st_name >= DynStrRegion.Size) + return object_error::parse_failed; + return StringRef(getDynamicString(Sym->st_name)); +} + +template <class ELFT> +ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *Section, + const Elf_Sym *Symb) const { + if (Symb->st_name == 0) { + const Elf_Shdr *ContainingSec = getSection(Symb); + if (ContainingSec) + return getSectionName(ContainingSec); } - return object_error::success; + + const Elf_Shdr *StrTab = getSection(Section->sh_link); + if (Symb->st_name >= StrTab->sh_size) + return object_error::parse_failed; + return StringRef(getString(StrTab, Symb->st_name)); } -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSectionName(const Elf_Shdr *section, - StringRef &Result) const { - Result = StringRef(getString(dot_shstrtab_sec, section->sh_name)); - return object_error::success; +template <class ELFT> +ErrorOr<StringRef> +ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const { + if (Section->sh_name >= dot_shstrtab_sec->sh_size) + return object_error::parse_failed; + return StringRef(getString(dot_shstrtab_sec, Section->sh_name)); } -template<class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Version, - bool &IsDefault) const { +template <class ELFT> +ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *symb, + bool &IsDefault) const { // Handle non-dynamic symbols. - if (section != getSection(DynamicSymbolTableIndex)) { + if (section != DynSymRegion.Addr && section != 0) { // Non-dynamic symbols can have versions in their names // A name of the form 'foo@V1' indicates version 'V1', non-default. // A name of the form 'foo@@V2' indicates version 'V2', default version. - StringRef Name; - error_code ec = getSymbolName(section, symb, Name); - if (ec != object_error::success) - return ec; + ErrorOr<StringRef> SymName = getSymbolName(section, symb); + if (!SymName) + return SymName; + StringRef Name = *SymName; size_t atpos = Name.find('@'); if (atpos == StringRef::npos) { - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } ++atpos; if (atpos < Name.size() && Name[atpos] == '@') { @@ -2962,21 +935,19 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, } else { IsDefault = false; } - Version = Name.substr(atpos); - return object_error::success; + return Name.substr(atpos); } // This is a dynamic symbol. Look in the GNU symbol version table. if (dot_gnu_version_sec == NULL) { // No version table. - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } // Determine the position in the symbol table of this entry. - const char *sec_start = (const char*)base() + section->sh_offset; - size_t entry_index = ((const char*)symb - sec_start)/section->sh_entsize; + size_t entry_index = ((const char *)symb - (const char *)DynSymRegion.Addr) / + DynSymRegion.EntSize; // Get the corresponding version index entry const Elf_Versym *vs = getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index); @@ -2985,16 +956,14 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, // Special markers for unversioned symbols. if (version_index == ELF::VER_NDX_LOCAL || version_index == ELF::VER_NDX_GLOBAL) { - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } // Lookup this symbol in the version table LoadVersionMap(); if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) - report_fatal_error("Symbol has version index without corresponding " - "define or reference entry"); + return object_error::parse_failed; const VersionMapEntry &entry = VersionMap[version_index]; // Get the version name string @@ -3005,7 +974,6 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, } else { name_offset = entry.getVernaux()->vna_name; } - Version = getString(dot_dynstr_sec, name_offset); // Set IsDefault if (entry.isVerdef()) { @@ -3014,57 +982,9 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, IsDefault = false; } - return object_error::success; -} - -/// FIXME: Maybe we should have a base ElfObjectFile that is not a template -/// and make these member functions? -static inline error_code getELFRelocationAddend(const RelocationRef R, - int64_t &Addend) { - const ObjectFile *Obj = R.getObjectFile(); - DataRefImpl DRI = R.getRawDataRefImpl(); - // Little-endian 32-bit - if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Big-endian 32-bit - if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Little-endian 64-bit - if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Big-endian 64-bit - if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); -} - -/// This is a generic interface for retrieving GNU symbol version -/// information from an ELFObjectFile. -static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, - StringRef &Version, - bool &IsDefault) { - // Little-endian 32-bit - if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 32-bit - if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Little-endian 64-bit - if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 64-bit - if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); + if (name_offset >= DynStrRegion.Size) + return object_error::parse_failed; + return StringRef(getDynamicString(name_offset)); } /// This function returns the hash value for a symbol in the .dynsym section @@ -3081,8 +1001,7 @@ static inline unsigned elf_hash(StringRef &symbolName) { } return h; } - -} -} +} // end namespace object +} // end namespace llvm #endif diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h new file mode 100644 index 0000000..962a3e2 --- /dev/null +++ b/include/llvm/Object/ELFObjectFile.h @@ -0,0 +1,1027 @@ +//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ELFObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELF_OBJECT_FILE_H +#define LLVM_OBJECT_ELF_OBJECT_FILE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cctype> +#include <limits> +#include <utility> + +namespace llvm { +namespace object { + +template <class ELFT> +class ELFObjectFile : public ObjectFile { +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + typedef typename ELFFile<ELFT>::uintX_t uintX_t; + + typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; + typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; + typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel; + typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela; + typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn; + + typedef typename ELFFile<ELFT>::Elf_Sym_Iter Elf_Sym_Iter; + typedef typename ELFFile<ELFT>::Elf_Shdr_Iter Elf_Shdr_Iter; + typedef typename ELFFile<ELFT>::Elf_Dyn_Iter Elf_Dyn_Iter; + +protected: + ELFFile<ELFT> EF; + + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; + virtual error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; + + virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; + virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; + + virtual error_code getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const; + virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; + virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const; + virtual error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const; + + uint64_t getROffset(DataRefImpl Rel) const; + StringRef getRelocationTypeName(uint32_t Type) const; + + /// \brief Get the relocation section that contains \a Rel. + const Elf_Shdr *getRelSection(DataRefImpl Rel) const { + return EF.getSection(Rel.d.a); + } + + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; + + Elf_Sym_Iter toELFSymIter(DataRefImpl Symb) const { + bool IsDynamic = Symb.p & 1; + if (IsDynamic) + return Elf_Sym_Iter( + EF.begin_dynamic_symbols().getEntSize(), + reinterpret_cast<const char *>(Symb.p & ~uintptr_t(1)), IsDynamic); + return Elf_Sym_Iter(EF.begin_symbols().getEntSize(), + reinterpret_cast<const char *>(Symb.p), IsDynamic); + } + + DataRefImpl toDRI(Elf_Sym_Iter Symb) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(Symb.get()) | + static_cast<uintptr_t>(Symb.isDynamic()); + return DRI; + } + + Elf_Shdr_Iter toELFShdrIter(DataRefImpl Sec) const { + return Elf_Shdr_Iter(EF.getHeader()->e_shentsize, + reinterpret_cast<const char *>(Sec.p)); + } + + DataRefImpl toDRI(Elf_Shdr_Iter Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(Sec.get()); + return DRI; + } + + DataRefImpl toDRI(const Elf_Shdr *Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(Sec); + return DRI; + } + + Elf_Dyn_Iter toELFDynIter(DataRefImpl Dyn) const { + return Elf_Dyn_Iter(EF.begin_dynamic_table().getEntSize(), + reinterpret_cast<const char *>(Dyn.p)); + } + + DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(Dyn.get()); + return DRI; + } + + // This flag is used for classof, to distinguish ELFObjectFile from + // its subclass. If more subclasses will be created, this flag will + // have to become an enum. + bool isDyldELFObject; + +public: + ELFObjectFile(MemoryBuffer *Object, error_code &ec); + + const Elf_Sym *getSymbol(DataRefImpl Symb) const; + + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + + virtual symbol_iterator begin_dynamic_symbols() const; + virtual symbol_iterator end_dynamic_symbols() const; + + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; + + error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; + error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, + bool &IsDefault) const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual StringRef getObjectType() const { return "ELF"; } + virtual unsigned getArch() const; + virtual StringRef getLoadName() const; + + const ELFFile<ELFT> *getELFFile() const { return &EF; } + + bool isDyldType() const { return isDyldELFObject; } + static inline bool classof(const Binary *v) { + return v->getType() == getELFType(ELFT::TargetEndianness == support::little, + ELFT::Is64Bits); + } +}; + +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. +typedef ELFObjectFile<ELFType<support::little, 2, false> > ELF32LEObjectFile; +typedef ELFObjectFile<ELFType<support::little, 2, true> > ELF64LEObjectFile; +typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile; +typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile; + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { + Result = SymbolRef(toDRI(++toELFSymIter(Symb)), this); + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { + ErrorOr<StringRef> Name = EF.getSymbolName(toELFSymIter(Symb)); + if (!Name) + return Name; + Result = *Name; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { + DataRefImpl Symb = SymRef.getRawDataRefImpl(); + const Elf_Sym *symb = getSymbol(Symb); + ErrorOr<StringRef> Ver = + EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); + if (!Ver) + return Ver; + Version = *Ver; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec; + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_COMMON: + // Unintialized symbols have no offset in the object file + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = ESym->st_value; + return object_error::success; + default: + ESec = EF.getSection(ESym); + } + + switch (ESym->getType()) { + case ELF::STT_SECTION: + Result = ESec ? ESec->sh_offset : UnknownAddressOrSize; + return object_error::success; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + Result = ESym->st_value + (ESec ? ESec->sh_offset : 0); + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec; + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_COMMON: + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = ESym->st_value; + return object_error::success; + default: + ESec = EF.getSection(ESym); + } + + switch (ESym->getType()) { + case ELF::STT_SECTION: + Result = ESec ? ESec->sh_addr : UnknownAddressOrSize; + return object_error::success; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + bool IsRelocatable; + switch (EF.getHeader()->e_type) { + case ELF::ET_EXEC: + case ELF::ET_DYN: + IsRelocatable = false; + break; + default: + IsRelocatable = true; + } + Result = ESym->st_value; + + // Clear the ARM/Thumb indicator flag. + if (EF.getHeader()->e_machine == ELF::EM_ARM) + Result &= ~1; + + if (IsRelocatable && ESec != 0) + Result += ESec->sh_addr; + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { + Elf_Sym_Iter Sym = toELFSymIter(Symb); + if (Sym->st_shndx == ELF::SHN_COMMON) + Res = Sym->st_value; + else + Res = 0; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { + Result = toELFSymIter(Symb)->st_size; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + + switch (ESym->getType()) { + case ELF::STT_NOTYPE: + Result = SymbolRef::ST_Unknown; + break; + case ELF::STT_SECTION: + Result = SymbolRef::ST_Debug; + break; + case ELF::STT_FILE: + Result = SymbolRef::ST_File; + break; + case ELF::STT_FUNC: + Result = SymbolRef::ST_Function; + break; + case ELF::STT_OBJECT: + case ELF::STT_COMMON: + case ELF::STT_TLS: + Result = SymbolRef::ST_Data; + break; + default: + Result = SymbolRef::ST_Other; + break; + } + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + + Result = SymbolRef::SF_None; + + if (ESym->getBinding() != ELF::STB_LOCAL) + Result |= SymbolRef::SF_Global; + + if (ESym->getBinding() == ELF::STB_WEAK) + Result |= SymbolRef::SF_Weak; + + if (ESym->st_shndx == ELF::SHN_ABS) + Result |= SymbolRef::SF_Absolute; + + if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || + ESym == &*EF.begin_symbols()) + Result |= SymbolRef::SF_FormatSpecific; + + if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) + Result |= SymbolRef::SF_Undefined; + + if (ESym->getType() == ELF::STT_COMMON || + EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) + Result |= SymbolRef::SF_Common; + + if (ESym->getType() == ELF::STT_TLS) + Result |= SymbolRef::SF_ThreadLocal; + + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec = EF.getSection(ESym); + if (!ESec) + Res = end_sections(); + else { + DataRefImpl Sec; + Sec.p = reinterpret_cast<intptr_t>(ESec); + Res = section_iterator(SectionRef(Sec, this)); + } + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + const Elf_Sym *ESym = getSymbol(Symb); + Val = ESym->st_value; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { + Result = SectionRef(toDRI(++toELFShdrIter(Sec)), this); + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ErrorOr<StringRef> Name = EF.getSectionName(&*toELFShdrIter(Sec)); + if (!Name) + return Name; + Result = *Name; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_addr; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_size; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_addralign; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_PROGBITS; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template <class ELFT> +error_code +ELFObjectFile<ELFT>::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { + Elf_Sym_Iter ESym = toELFSymIter(Symb); + + uintX_t Index = ESym->st_shndx; + bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE; + + Result = !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); + return object_error::success; +} + +template <class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const { + DataRefImpl RelData; + uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.begin_sections().get()); + RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + RelData.d.b = 0; + return relocation_iterator(RelocationRef(RelData, this)); +} + +template <class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { + DataRefImpl RelData; + uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.begin_sections().get()); + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) + RelData.d.b = 0; + else + RelData.d.b = S->sh_size / S->sh_entsize; + + return relocation_iterator(RelocationRef(RelData, this)); +} + +template <class ELFT> +section_iterator +ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { + if (EF.getHeader()->e_type != ELF::ET_REL) + return end_sections(); + + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + uintX_t Type = EShdr->sh_type; + if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) + return end_sections(); + + const Elf_Shdr *R = EF.getSection(EShdr->sh_info); + return section_iterator(SectionRef(toDRI(R), this)); +} + +// Relocations +template <class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationNext(DataRefImpl Rel, + RelocationRef &Result) const { + ++Rel.d.b; + Result = RelocationRef(Rel, this); + return object_error::success; +} + +template <class ELFT> +symbol_iterator +ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { + uint32_t symbolIdx; + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); + break; + } + } + if (!symbolIdx) + return end_symbols(); + + const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); + + DataRefImpl SymbolData; + switch (SymSec->sh_type) { + default: + report_fatal_error("Invalid symbol table section type!"); + case ELF::SHT_SYMTAB: + SymbolData = toDRI(EF.begin_symbols() + symbolIdx); + break; + case ELF::SHT_DYNSYM: + SymbolData = toDRI(EF.begin_dynamic_symbols() + symbolIdx); + break; + } + + return symbol_iterator(SymbolRef(SymbolData, this)); +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { + Result = getROffset(Rel); + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { + Result = getROffset(Rel); + return object_error::success; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: + return getRel(Rel)->r_offset; + case ELF::SHT_RELA: + return getRela(Rel)->r_offset; + } +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, + uint64_t &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + Result = getRel(Rel)->getType(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + Result = getRela(Rel)->getType(EF.isMips64EL()); + break; + } + } + return object_error::success; +} + +template <class ELFT> +StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { + return getELFRelocationTypeName(EF.getHeader()->e_machine, Type); +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + uint32_t type; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(Rel)->getType(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + type = getRela(Rel)->getType(EF.isMips64EL()); + break; + } + } + + EF.getRelocationTypeName(type, Result); + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel, + int64_t &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + Result = 0; + return object_error::success; + } + case ELF::SHT_RELA: { + Result = getRela(Rel)->r_addend; + return object_error::success; + } + } +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationValueString( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + uint8_t type; + StringRef res; + int64_t addend = 0; + uint16_t symbol_index = 0; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(Rel)->getType(EF.isMips64EL()); + symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL()); + // TODO: Read implicit addend from section data. + break; + } + case ELF::SHT_RELA: { + type = getRela(Rel)->getType(EF.isMips64EL()); + symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL()); + addend = getRela(Rel)->r_addend; + break; + } + } + const Elf_Sym *symb = + EF.template getEntry<Elf_Sym>(sec->sh_link, symbol_index); + ErrorOr<StringRef> SymName = + EF.getSymbolName(EF.getSection(sec->sh_link), symb); + if (!SymName) + return SymName; + switch (EF.getHeader()->e_machine) { + case ELF::EM_X86_64: + switch (type) { + case ELF::R_X86_64_PC8: + case ELF::R_X86_64_PC16: + case ELF::R_X86_64_PC32: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P"; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + case ELF::R_X86_64_8: + case ELF::R_X86_64_16: + case ELF::R_X86_64_32: + case ELF::R_X86_64_32S: + case ELF::R_X86_64_64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + default: + res = "Unknown"; + } + break; + case ELF::EM_AARCH64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName; + if (addend != 0) + fmt << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + break; + } + case ELF::EM_ARM: + case ELF::EM_HEXAGON: + res = *SymName; + break; + default: + res = "Unknown"; + } + if (Result.empty()) + Result.append(res.begin(), res.end()); + return object_error::success; +} + +template <class ELFT> +const typename ELFFile<ELFT>::Elf_Sym * +ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const { + return &*toELFSymIter(Symb); +} + +template <class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rel * +ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { + return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); +} + +template <class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rela * +ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { + return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); +} + +template <class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(getELFType(static_cast<endianness>(ELFT::TargetEndianness) == + support::little, + ELFT::Is64Bits), + Object), + EF(Object, ec) {} + +template <class ELFT> +symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); +} + +template <class ELFT> +symbol_iterator ELFObjectFile<ELFT>::end_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); +} + +template <class ELFT> +symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); +} + +template <class ELFT> +symbol_iterator ELFObjectFile<ELFT>::end_dynamic_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); +} + +template <class ELFT> +section_iterator ELFObjectFile<ELFT>::begin_sections() const { + return section_iterator(SectionRef(toDRI(EF.begin_sections()), this)); +} + +template <class ELFT> +section_iterator ELFObjectFile<ELFT>::end_sections() const { + return section_iterator(SectionRef(toDRI(EF.end_sections()), this)); +} + +template <class ELFT> +StringRef ELFObjectFile<ELFT>::getLoadName() const { + Elf_Dyn_Iter DI = EF.begin_dynamic_table(); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + while (DI != DE && DI->getTag() != ELF::DT_SONAME) + ++DI; + + if (DI != DE) + return EF.getDynamicString(DI->getVal()); + return ""; +} + +template <class ELFT> +library_iterator ELFObjectFile<ELFT>::begin_libraries_needed() const { + Elf_Dyn_Iter DI = EF.begin_dynamic_table(); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + while (DI != DE && DI->getTag() != ELF::DT_SONAME) + ++DI; + + return library_iterator(LibraryRef(toDRI(DI), this)); +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { + Elf_Dyn_Iter DI = toELFDynIter(Data); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + // Skip to the next DT_NEEDED entry. + do + ++DI; + while (DI != DE && DI->getTag() != ELF::DT_NEEDED); + + Result = LibraryRef(toDRI(DI), this); + return object_error::success; +} + +template <class ELFT> +error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { + Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); + return object_error::success; +} + +template <class ELFT> +library_iterator ELFObjectFile<ELFT>::end_libraries_needed() const { + return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; +} + +template <class ELFT> +StringRef ELFObjectFile<ELFT>::getFileFormatName() const { + switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + case ELF::ELFCLASS32: + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return "ELF32-i386"; + case ELF::EM_X86_64: + return "ELF32-x86-64"; + case ELF::EM_ARM: + return "ELF32-arm"; + case ELF::EM_HEXAGON: + return "ELF32-hexagon"; + case ELF::EM_MIPS: + return "ELF32-mips"; + case ELF::EM_PPC: + return "ELF32-ppc"; + default: + return "ELF32-unknown"; + } + case ELF::ELFCLASS64: + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return "ELF64-i386"; + case ELF::EM_X86_64: + return "ELF64-x86-64"; + case ELF::EM_AARCH64: + return "ELF64-aarch64"; + case ELF::EM_PPC64: + return "ELF64-ppc64"; + case ELF::EM_S390: + return "ELF64-s390"; + default: + return "ELF64-unknown"; + } + default: + // FIXME: Proper error handling. + report_fatal_error("Invalid ELFCLASS!"); + } +} + +template <class ELFT> +unsigned ELFObjectFile<ELFT>::getArch() const { + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return Triple::x86; + case ELF::EM_X86_64: + return Triple::x86_64; + case ELF::EM_AARCH64: + return Triple::aarch64; + case ELF::EM_ARM: + return Triple::arm; + case ELF::EM_HEXAGON: + return Triple::hexagon; + case ELF::EM_MIPS: + return (ELFT::TargetEndianness == support::little) ? Triple::mipsel + : Triple::mips; + case ELF::EM_PPC64: + return (ELFT::TargetEndianness == support::little) ? Triple::ppc64le + : Triple::ppc64; + case ELF::EM_S390: + return Triple::systemz; + default: + return Triple::UnknownArch; + } +} + +/// FIXME: Maybe we should have a base ElfObjectFile that is not a template +/// and make these member functions? +static inline error_code getELFRelocationAddend(const RelocationRef R, + int64_t &Addend) { + const ObjectFile *Obj = R.getObjectFile(); + DataRefImpl DRI = R.getRawDataRefImpl(); + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); +} + +/// This is a generic interface for retrieving GNU symbol version +/// information from an ELFObjectFile. +static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, + const SymbolRef &Sym, + StringRef &Version, + bool &IsDefault) { + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); +} +} +} + +#endif diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h new file mode 100644 index 0000000..84b6031 --- /dev/null +++ b/include/llvm/Object/ELFTypes.h @@ -0,0 +1,463 @@ +//===- ELFTypes.h - Endian specific types for ELF ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELF_TYPES_H +#define LLVM_OBJECT_ELF_TYPES_H + +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace object { + +using support::endianness; + +template <endianness target_endianness, std::size_t max_alignment, + bool is64Bits> +struct ELFType { + static const endianness TargetEndianness = target_endianness; + static const std::size_t MaxAlignment = max_alignment; + static const bool Is64Bits = is64Bits; +}; + +template <typename T, int max_align> struct MaximumAlignment { + enum { value = AlignOf<T>::Alignment > max_align ? max_align + : AlignOf<T>::Alignment + }; +}; + +// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. +template <endianness target_endianness, std::size_t max_alignment> +struct ELFDataTypeTypedefHelperCommon { + typedef support::detail::packed_endian_specific_integral< + uint16_t, target_endianness, + MaximumAlignment<uint16_t, max_alignment>::value> Elf_Half; + typedef support::detail::packed_endian_specific_integral< + uint32_t, target_endianness, + MaximumAlignment<uint32_t, max_alignment>::value> Elf_Word; + typedef support::detail::packed_endian_specific_integral< + int32_t, target_endianness, + MaximumAlignment<int32_t, max_alignment>::value> Elf_Sword; + typedef support::detail::packed_endian_specific_integral< + uint64_t, target_endianness, + MaximumAlignment<uint64_t, max_alignment>::value> Elf_Xword; + typedef support::detail::packed_endian_specific_integral< + int64_t, target_endianness, + MaximumAlignment<int64_t, max_alignment>::value> Elf_Sxword; +}; + +template <class ELFT> struct ELFDataTypeTypedefHelper; + +/// ELF 32bit types. +template <endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, false> > + : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { + typedef uint32_t value_type; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Off; +}; + +/// ELF 64bit types. +template <endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, true> > + : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { + typedef uint64_t value_type; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Off; +}; + +// I really don't like doing this, but the alternative is copypasta. +#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Addr \ + Elf_Addr; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Off \ + Elf_Off; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Half \ + Elf_Half; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Word \ + Elf_Word; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Sword \ + Elf_Sword; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Xword \ + Elf_Xword; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Sxword \ + Elf_Sxword; + +#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ + LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ + ELFT::Is64Bits) + +// Section header. +template <class ELFT> struct Elf_Shdr_Base; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Word sh_name; // Section name (index into string table) + Elf_Word sh_type; // Section type (SHT_*) + Elf_Word sh_flags; // Section flags (SHF_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Word sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Word sh_addralign; // Section address alignment + Elf_Word sh_entsize; // Size of records contained within the section +}; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Word sh_name; // Section name (index into string table) + Elf_Word sh_type; // Section type (SHT_*) + Elf_Xword sh_flags; // Section flags (SHF_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Xword sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Xword sh_addralign; // Section address alignment + Elf_Xword sh_entsize; // Size of records contained within the section +}; + +template <class ELFT> +struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { + using Elf_Shdr_Base<ELFT>::sh_entsize; + using Elf_Shdr_Base<ELFT>::sh_size; + + /// @brief Get the number of entities this section contains if it has any. + unsigned getEntityCount() const { + if (sh_entsize == 0) + return 0; + return sh_size / sh_entsize; + } +}; + +template <class ELFT> struct Elf_Sym_Base; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Word st_name; // Symbol name (index into string table) + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in +}; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Word st_name; // Symbol name (index into string table) + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Xword st_size; // Size of the symbol +}; + +template <class ELFT> +struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { + using Elf_Sym_Base<ELFT>::st_info; + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section +/// (.gnu.version). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Versym_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) +}; + +template <class ELFT> struct Elf_Verdaux_Impl; + +/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section +/// (.gnu.version_d). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Verdef_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; + Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) + Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) + Elf_Half vd_ndx; // Version index, used in .gnu.version entries + Elf_Half vd_cnt; // Number of Verdaux entries + Elf_Word vd_hash; // Hash of name + Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) + Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) + + /// Get the first Verdaux entry for this Verdef. + const Elf_Verdaux *getAux() const { + return reinterpret_cast<const Elf_Verdaux *>((const char *)this + vd_aux); + } +}; + +/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef +/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Verdaux_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word vda_name; // Version name (offset in string table) + Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) +}; + +/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed +/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Verneed_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) + Elf_Half vn_cnt; // Number of associated Vernaux entries + Elf_Word vn_file; // Library name (string table offset) + Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) + Elf_Word vn_next; // Offset to next Verneed entry (in bytes) +}; + +/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed +/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. +template <class ELFT> +struct Elf_Vernaux_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word vna_hash; // Hash of dependency name + Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) + Elf_Half vna_other; // Version index, used in .gnu.version entries + Elf_Word vna_name; // Dependency name + Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) +}; + +/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic +/// table section (.dynamic) look like. +template <class ELFT> struct Elf_Dyn_Base; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Sword d_tag; + union { + Elf_Word d_val; + Elf_Addr d_ptr; + } d_un; +}; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Sxword d_tag; + union { + Elf_Xword d_val; + Elf_Addr d_ptr; + } d_un; +}; + +/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. +template <class ELFT> +struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { + using Elf_Dyn_Base<ELFT>::d_tag; + using Elf_Dyn_Base<ELFT>::d_un; + int64_t getTag() const { return d_tag; } + uint64_t getVal() const { return d_un.d_val; } + uint64_t getPtr() const { return d_un.ptr; } +}; + +// Elf_Rel: Elf Relocation +template <class ELFT, bool isRela> struct Elf_Rel_Base; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { r_info = R; } +}; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + + uint64_t getRInfo(bool isMips64EL) const { + uint64_t t = r_info; + if (!isMips64EL) + return t; + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + } + void setRInfo(uint64_t R) { + // FIXME: Add mips64el support. + r_info = R; + } +}; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + Elf_Sword r_addend; // Compute value for relocatable field by adding this + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { r_info = R; } +}; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. + + uint64_t getRInfo(bool isMips64EL) const { + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + uint64_t t = r_info; + if (!isMips64EL) + return t; + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + } + void setRInfo(uint64_t R) { + // FIXME: Add mips64el support. + r_info = R; + } +}; + +template <class ELFT, bool isRela> struct Elf_Rel_Impl; + +template <endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>, + isRela> : Elf_Rel_Base< + ELFType<TargetEndianness, MaxAlign, true>, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return (uint32_t)(this->getRInfo(isMips64EL) >> 32); + } + uint32_t getType(bool isMips64EL) const { + return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); + } + void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } + void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(uint32_t s, uint32_t t) { + this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL)); + } +}; + +template <endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>, + isRela> : Elf_Rel_Base< + ELFType<TargetEndianness, MaxAlign, false>, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return this->getRInfo(isMips64EL) >> 8; + } + unsigned char getType(bool isMips64EL) const { + return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); + } + void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(uint32_t s, unsigned char t) { + this->setRInfo((s << 8) + t); + } +}; + +template <class ELFT> +struct Elf_Ehdr_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes + Elf_Half e_type; // Type of file (see ET_*) + Elf_Half e_machine; // Required architecture for this file (see EM_*) + Elf_Word e_version; // Must be equal to 1 + Elf_Addr e_entry; // Address to jump to in order to start program + Elf_Off e_phoff; // Program header table's file offset, in bytes + Elf_Off e_shoff; // Section header table's file offset, in bytes + Elf_Word e_flags; // Processor-specific flags + Elf_Half e_ehsize; // Size of ELF header, in bytes + Elf_Half e_phentsize; // Size of an entry in the program header table + Elf_Half e_phnum; // Number of entries in the program header table + Elf_Half e_shentsize; // Size of an entry in the section header table + Elf_Half e_shnum; // Number of entries in the section header table + Elf_Half e_shstrndx; // Section header table index of section name + // string table + bool checkMagic() const { + return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } +}; + +template <class ELFT> struct Elf_Phdr_Impl; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Word p_type; // Type of segment + Elf_Off p_offset; // FileOffset where segment is located, in bytes + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Word p_flags; // Segment flags + Elf_Word p_align; // Segment alignment constraint +}; + +template <endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Word p_type; // Type of segment + Elf_Word p_flags; // Segment flags + Elf_Off p_offset; // FileOffset where segment is located, in bytes + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Xword p_align; // Segment alignment constraint +}; + +} // end namespace object. +} // end namespace llvm. + +#endif diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 50435d6..100613a 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -18,10 +18,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/MachOFormat.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MachO.h" -#include "llvm/Support/raw_ostream.h" namespace llvm { namespace object { @@ -55,7 +53,7 @@ class MachOObjectFile : public ObjectFile { public: struct LoadCommandInfo { const char *Ptr; // Where in memory the load command is. - macho::LoadCommand C; // The command itself. + MachO::load_command C; // The command itself. }; MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, @@ -69,7 +67,6 @@ public: virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; @@ -91,8 +88,8 @@ public: virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; @@ -131,8 +128,8 @@ public: virtual StringRef getLoadName() const; - relocation_iterator getSectionRelBegin(unsigned Index) const; - relocation_iterator getSectionRelEnd(unsigned Index) const; + relocation_iterator section_rel_begin(unsigned Index) const; + relocation_iterator section_rel_end(unsigned Index) const; dice_iterator begin_dices() const; dice_iterator end_dices() const; @@ -148,50 +145,53 @@ public: ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const; // MachO specific Info about relocations. - bool isRelocationScattered(const macho::RelocationEntry &RE) const; - unsigned getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const; - bool getPlainRelocationExternal(const macho::RelocationEntry &RE) const; - bool getScatteredRelocationScattered(const macho::RelocationEntry &RE) const; - uint32_t getScatteredRelocationValue(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationAddress(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationPCRel(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationLength(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationType(const macho::RelocationEntry &RE) const; - SectionRef getRelocationSection(const macho::RelocationEntry &RE) const; + bool isRelocationScattered(const MachO::any_relocation_info &RE) const; + unsigned getPlainRelocationSymbolNum( + const MachO::any_relocation_info &RE) const; + bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const; + bool getScatteredRelocationScattered( + const MachO::any_relocation_info &RE) const; + uint32_t getScatteredRelocationValue( + const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; + SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const; // Walk load commands. LoadCommandInfo getFirstLoadCommandInfo() const; LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const; // MachO specific structures. - macho::Section getSection(DataRefImpl DRI) const; - macho::Section64 getSection64(DataRefImpl DRI) const; - macho::Section getSection(const LoadCommandInfo &L, unsigned Index) const; - macho::Section64 getSection64(const LoadCommandInfo &L, unsigned Index) const; - macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const; - macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const; - - macho::LinkeditDataLoadCommand + MachO::section getSection(DataRefImpl DRI) const; + MachO::section_64 getSection64(DataRefImpl DRI) const; + MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const; + MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const; + MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const; + MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const; + + MachO::linkedit_data_command getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; - macho::SegmentLoadCommand + MachO::segment_command getSegmentLoadCommand(const LoadCommandInfo &L) const; - macho::Segment64LoadCommand + MachO::segment_command_64 getSegment64LoadCommand(const LoadCommandInfo &L) const; - macho::LinkerOptionsLoadCommand + MachO::linker_options_command getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; - macho::RelocationEntry getRelocation(DataRefImpl Rel) const; - macho::DataInCodeTableEntry getDice(DataRefImpl Rel) const; - macho::Header getHeader() const; - macho::Header64Ext getHeader64Ext() const; - macho::IndirectSymbolTableEntry - getIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, + MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; + MachO::data_in_code_entry getDice(DataRefImpl Rel) const; + MachO::mach_header getHeader() const; + MachO::mach_header_64 getHeader64() const; + uint32_t + getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC, unsigned Index) const; - macho::DataInCodeTableEntry getDataInCodeTableEntry(uint32_t DataOffset, - unsigned Index) const; - macho::SymtabLoadCommand getSymtabLoadCommand() const; - macho::DysymtabLoadCommand getDysymtabLoadCommand() const; - macho::LinkeditDataLoadCommand getDataInCodeLoadCommand() const; + MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const; + MachO::symtab_command getSymtabLoadCommand() const; + MachO::dysymtab_command getDysymtabLoadCommand() const; + MachO::linkedit_data_command getDataInCodeLoadCommand() const; StringRef getStringTableData() const; bool is64Bit() const; @@ -225,8 +225,8 @@ inline bool DiceRef::operator<(const DiceRef &Other) const { inline error_code DiceRef::getNext(DiceRef &Result) const { DataRefImpl Rel = DicePimpl; - const macho::DataInCodeTableEntry *P = - reinterpret_cast<const macho::DataInCodeTableEntry *>(Rel.p); + const MachO::data_in_code_entry *P = + reinterpret_cast<const MachO::data_in_code_entry *>(Rel.p); Rel.p = reinterpret_cast<uintptr_t>(P + 1); Result = DiceRef(Rel, OwningObject); return object_error::success; @@ -239,24 +239,24 @@ inline error_code DiceRef::getNext(DiceRef &Result) const { inline error_code DiceRef::getOffset(uint32_t &Result) const { const MachOObjectFile *MachOOF = static_cast<const MachOObjectFile *>(OwningObject); - macho::DataInCodeTableEntry Dice = MachOOF->getDice(DicePimpl); - Result = Dice.Offset; + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.offset; return object_error::success; } inline error_code DiceRef::getLength(uint16_t &Result) const { const MachOObjectFile *MachOOF = static_cast<const MachOObjectFile *>(OwningObject); - macho::DataInCodeTableEntry Dice = MachOOF->getDice(DicePimpl); - Result = Dice.Length; + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.length; return object_error::success; } inline error_code DiceRef::getKind(uint16_t &Result) const { const MachOObjectFile *MachOOF = static_cast<const MachOObjectFile *>(OwningObject); - macho::DataInCodeTableEntry Dice = MachOOF->getDice(DicePimpl); - Result = Dice.Kind; + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.kind; return object_error::success; } diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h deleted file mode 100644 index 96ee8a7..0000000 --- a/include/llvm/Object/MachOFormat.h +++ /dev/null @@ -1,433 +0,0 @@ -//===- MachOFormat.h - Mach-O Format Structures And Constants ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares various structures and constants which are platform -// independent and can be shared by any client which wishes to interact with -// Mach object files. -// -// The definitions here are purposely chosen to match the LLVM style as opposed -// to following the platform specific definition of the format. -// -// On a Mach system, see the <mach-o/...> includes for more information, in -// particular <mach-o/loader.h>. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MACHOFORMAT_H -#define LLVM_OBJECT_MACHOFORMAT_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { -namespace object { - -/// General Mach platform information. -namespace mach { - /// @name CPU Type and Subtype Information - /// { - - /// \brief Capability bits used in CPU type encoding. - enum CPUTypeFlagsMask { - CTFM_ArchMask = 0xFF000000, - CTFM_ArchABI64 = 0x01000000 - }; - - /// \brief Machine type IDs used in CPU type encoding. - enum CPUTypeMachine { - CTM_i386 = 7, - CTM_x86_64 = CTM_i386 | CTFM_ArchABI64, - CTM_ARM = 12, - CTM_SPARC = 14, - CTM_PowerPC = 18, - CTM_PowerPC64 = CTM_PowerPC | CTFM_ArchABI64 - }; - - /// \brief Capability bits used in CPU subtype encoding. - enum CPUSubtypeFlagsMask { - CSFM_SubtypeMask = 0xFF000000, - CSFM_SubtypeLib64 = 0x80000000 - }; - - /// \brief ARM Machine Subtypes. - enum CPUSubtypeARM { - CSARM_ALL = 0, - CSARM_V4T = 5, - CSARM_V6 = 6, - CSARM_V5TEJ = 7, - CSARM_XSCALE = 8, - CSARM_V7 = 9, - CSARM_V7F = 10, - CSARM_V7S = 11, - CSARM_V7K = 12, - CSARM_V6M = 14, - CSARM_V7M = 15, - CSARM_V7EM = 16 - }; - - /// \brief PowerPC Machine Subtypes. - enum CPUSubtypePowerPC { - CSPPC_ALL = 0 - }; - - /// \brief SPARC Machine Subtypes. - enum CPUSubtypeSPARC { - CSSPARC_ALL = 0 - }; - - /// \brief x86 Machine Subtypes. - enum CPUSubtypeX86 { - CSX86_ALL = 3 - }; - - /// @} - -} // end namespace mach - -/// Format information for Mach object files. -namespace macho { - /// \brief Constants for structure sizes. - enum StructureSizes { - Header32Size = 28, - Header64Size = 32, - FatHeaderSize = 8, - FatArchHeaderSize = 20, - SegmentLoadCommand32Size = 56, - SegmentLoadCommand64Size = 72, - Section32Size = 68, - Section64Size = 80, - SymtabLoadCommandSize = 24, - DysymtabLoadCommandSize = 80, - Nlist32Size = 12, - Nlist64Size = 16, - RelocationInfoSize = 8, - LinkeditLoadCommandSize = 16 - }; - - /// \brief Constants for header magic field. - enum HeaderMagic { - HM_Object32 = 0xFEEDFACE, ///< 32-bit mach object file - HM_Object64 = 0xFEEDFACF, ///< 64-bit mach object file - HM_Universal = 0xCAFEBABE ///< Universal object file - }; - - /// \brief Header common to all Mach object files. - struct Header { - uint32_t Magic; - uint32_t CPUType; - uint32_t CPUSubtype; - uint32_t FileType; - uint32_t NumLoadCommands; - uint32_t SizeOfLoadCommands; - uint32_t Flags; - }; - - /// \brief Extended header for 64-bit object files. - struct Header64Ext { - uint32_t Reserved; - }; - - /// \brief Header for universal object files. - struct FatHeader { - uint32_t Magic; - uint32_t NumFatArch; - }; - - /// \brief Header for a single-architecture object file in a - /// universal binary. - struct FatArchHeader { - uint32_t CPUType; - uint32_t CPUSubtype; - uint32_t Offset; - uint32_t Size; - uint32_t Align; - }; - - // See <mach-o/loader.h>. - enum HeaderFileType { - HFT_Object = 0x1 - }; - - enum HeaderFlags { - HF_SubsectionsViaSymbols = 0x2000 - }; - - enum LoadCommandType { - LCT_Segment = 0x1, - LCT_Symtab = 0x2, - LCT_Dysymtab = 0xb, - LCT_Segment64 = 0x19, - LCT_UUID = 0x1b, - LCT_CodeSignature = 0x1d, - LCT_SegmentSplitInfo = 0x1e, - LCT_FunctionStarts = 0x26, - LCT_DataInCode = 0x29, - LCT_LinkerOptions = 0x2D - }; - - /// \brief Load command structure. - struct LoadCommand { - uint32_t Type; - uint32_t Size; - }; - - /// @name Load Command Structures - /// @{ - - struct SegmentLoadCommand { - uint32_t Type; - uint32_t Size; - char Name[16]; - uint32_t VMAddress; - uint32_t VMSize; - uint32_t FileOffset; - uint32_t FileSize; - uint32_t MaxVMProtection; - uint32_t InitialVMProtection; - uint32_t NumSections; - uint32_t Flags; - }; - - struct Segment64LoadCommand { - uint32_t Type; - uint32_t Size; - char Name[16]; - uint64_t VMAddress; - uint64_t VMSize; - uint64_t FileOffset; - uint64_t FileSize; - uint32_t MaxVMProtection; - uint32_t InitialVMProtection; - uint32_t NumSections; - uint32_t Flags; - }; - - struct SymtabLoadCommand { - uint32_t Type; - uint32_t Size; - uint32_t SymbolTableOffset; - uint32_t NumSymbolTableEntries; - uint32_t StringTableOffset; - uint32_t StringTableSize; - }; - - struct DysymtabLoadCommand { - uint32_t Type; - uint32_t Size; - - uint32_t LocalSymbolsIndex; - uint32_t NumLocalSymbols; - - uint32_t ExternalSymbolsIndex; - uint32_t NumExternalSymbols; - - uint32_t UndefinedSymbolsIndex; - uint32_t NumUndefinedSymbols; - - uint32_t TOCOffset; - uint32_t NumTOCEntries; - - uint32_t ModuleTableOffset; - uint32_t NumModuleTableEntries; - - uint32_t ReferenceSymbolTableOffset; - uint32_t NumReferencedSymbolTableEntries; - - uint32_t IndirectSymbolTableOffset; - uint32_t NumIndirectSymbolTableEntries; - - uint32_t ExternalRelocationTableOffset; - uint32_t NumExternalRelocationTableEntries; - - uint32_t LocalRelocationTableOffset; - uint32_t NumLocalRelocationTableEntries; - }; - - struct LinkeditDataLoadCommand { - uint32_t Type; - uint32_t Size; - uint32_t DataOffset; - uint32_t DataSize; - }; - - struct LinkerOptionsLoadCommand { - uint32_t Type; - uint32_t Size; - uint32_t Count; - // Load command is followed by Count number of zero-terminated UTF8 strings, - // and then zero-filled to be 4-byte aligned. - }; - - /// @} - /// @name Section Data - /// @{ - - enum SectionFlags { - SF_PureInstructions = 0x80000000 - }; - - struct Section { - char Name[16]; - char SegmentName[16]; - uint32_t Address; - uint32_t Size; - uint32_t Offset; - uint32_t Align; - uint32_t RelocationTableOffset; - uint32_t NumRelocationTableEntries; - uint32_t Flags; - uint32_t Reserved1; - uint32_t Reserved2; - }; - struct Section64 { - char Name[16]; - char SegmentName[16]; - uint64_t Address; - uint64_t Size; - uint32_t Offset; - uint32_t Align; - uint32_t RelocationTableOffset; - uint32_t NumRelocationTableEntries; - uint32_t Flags; - uint32_t Reserved1; - uint32_t Reserved2; - uint32_t Reserved3; - }; - - /// @} - /// @name Symbol Table Entries - /// @{ - - struct SymbolTableEntry { - uint32_t StringIndex; - uint8_t Type; - uint8_t SectionIndex; - uint16_t Flags; - uint32_t Value; - }; - // Despite containing a uint64_t, this structure is only 4-byte aligned within - // a MachO file. -#pragma pack(push) -#pragma pack(4) - struct Symbol64TableEntry { - uint32_t StringIndex; - uint8_t Type; - uint8_t SectionIndex; - uint16_t Flags; - uint64_t Value; - }; -#pragma pack(pop) - - /// @} - /// @name Data-in-code Table Entry - /// @{ - - // See <mach-o/loader.h>. - enum DataRegionType { Data = 1, JumpTable8, JumpTable16, JumpTable32 }; - struct DataInCodeTableEntry { - uint32_t Offset; /* from mach_header to start of data region */ - uint16_t Length; /* number of bytes in data region */ - uint16_t Kind; /* a DataRegionType value */ - }; - - /// @} - /// @name Indirect Symbol Table - /// @{ - - struct IndirectSymbolTableEntry { - uint32_t Index; - }; - - /// @} - /// @name Relocation Data - /// @{ - - struct RelocationEntry { - uint32_t Word0; - uint32_t Word1; - }; - - /// @} - - // See <mach-o/nlist.h>. - enum SymbolTypeType { - STT_Undefined = 0x00, - STT_Absolute = 0x02, - STT_Section = 0x0e - }; - - enum SymbolTypeFlags { - // If any of these bits are set, then the entry is a stab entry number (see - // <mach-o/stab.h>. Otherwise the other masks apply. - STF_StabsEntryMask = 0xe0, - - STF_TypeMask = 0x0e, - STF_External = 0x01, - STF_PrivateExtern = 0x10 - }; - - /// IndirectSymbolFlags - Flags for encoding special values in the indirect - /// symbol entry. - enum IndirectSymbolFlags { - ISF_Local = 0x80000000, - ISF_Absolute = 0x40000000 - }; - - /// RelocationFlags - Special flags for addresses. - enum RelocationFlags { - RF_Scattered = 0x80000000 - }; - - /// Common relocation info types. - enum RelocationInfoType { - RIT_Vanilla = 0, - RIT_Pair = 1, - RIT_Difference = 2 - }; - - /// Generic relocation info types, which are shared by some (but not all) - /// platforms. - enum RelocationInfoType_Generic { - RIT_Generic_PreboundLazyPointer = 3, - RIT_Generic_LocalDifference = 4, - RIT_Generic_TLV = 5 - }; - - /// X86_64 uses its own relocation types. - enum RelocationInfoTypeX86_64 { - // Note that x86_64 doesn't even share the common relocation types. - RIT_X86_64_Unsigned = 0, - RIT_X86_64_Signed = 1, - RIT_X86_64_Branch = 2, - RIT_X86_64_GOTLoad = 3, - RIT_X86_64_GOT = 4, - RIT_X86_64_Subtractor = 5, - RIT_X86_64_Signed1 = 6, - RIT_X86_64_Signed2 = 7, - RIT_X86_64_Signed4 = 8, - RIT_X86_64_TLV = 9 - }; - - /// ARM uses its own relocation types. - enum RelocationInfoTypeARM { - RIT_ARM_LocalDifference = 3, - RIT_ARM_PreboundLazyPointer = 4, - RIT_ARM_Branch24Bit = 5, - RIT_ARM_ThumbBranch22Bit = 6, - RIT_ARM_ThumbBranch32Bit = 7, - RIT_ARM_Half = 8, - RIT_ARM_HalfDifference = 9 - - }; - -} // end namespace macho - -} // end namespace object -} // end namespace llvm - -#endif diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index 5743282..c5d1359 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -18,7 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/Binary.h" -#include "llvm/Object/MachOFormat.h" +#include "llvm/Support/MachO.h" namespace llvm { namespace object { @@ -35,7 +35,7 @@ public: /// \brief Index of object in the universal binary. uint32_t Index; /// \brief Descriptor of the object. - macho::FatArchHeader Header; + MachO::fat_arch Header; public: ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); @@ -50,7 +50,7 @@ public: } ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } - uint32_t getCPUType() const { return Header.CPUType; } + uint32_t getCPUType() const { return Header.cputype; } error_code getAsObjectFile(OwningPtr<ObjectFile> &Result) const; }; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index f434d63..9aea639 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -192,7 +192,7 @@ public: ST_Other }; - enum Flags { + enum Flags LLVM_ENUM_INT_TYPE(unsigned) { SF_None = 0, SF_Undefined = 1U << 0, // Symbol is defined in another object file SF_Global = 1U << 1, // Global symbol @@ -221,10 +221,6 @@ public: error_code getSize(uint64_t &Result) const; error_code getType(SymbolRef::Type &Result) const; - /// Returns the ascii char that should be displayed in a symbol table dump via - /// nm for this symbol. - error_code getNMTypeChar(char &Result) const; - /// Get symbol flags (bitwise OR of SymbolRef::Flags) error_code getFlags(uint32_t &Result) const; @@ -296,7 +292,6 @@ protected: virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const = 0; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const = 0; virtual error_code getSymbolSection(DataRefImpl Symb, @@ -322,8 +317,8 @@ protected: virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const =0; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const = 0; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const = 0; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const = 0; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; // Same as above for RelocationRef. @@ -431,10 +426,6 @@ inline error_code SymbolRef::getSize(uint64_t &Result) const { return OwningObject->getSymbolSize(SymbolPimpl, Result); } -inline error_code SymbolRef::getNMTypeChar(char &Result) const { - return OwningObject->getSymbolNMTypeChar(SymbolPimpl, Result); -} - inline error_code SymbolRef::getFlags(uint32_t &Result) const { return OwningObject->getSymbolFlags(SymbolPimpl, Result); } @@ -528,11 +519,11 @@ inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { } inline relocation_iterator SectionRef::begin_relocations() const { - return OwningObject->getSectionRelBegin(SectionPimpl); + return OwningObject->section_rel_begin(SectionPimpl); } inline relocation_iterator SectionRef::end_relocations() const { - return OwningObject->getSectionRelEnd(SectionPimpl); + return OwningObject->section_rel_end(SectionPimpl); } inline section_iterator SectionRef::getRelocatedSection() const { diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index b1eb4e6..97912fe 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -18,7 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td index 32cc2c0..963389f 100644 --- a/include/llvm/Option/OptParser.td +++ b/include/llvm/Option/OptParser.td @@ -44,6 +44,8 @@ def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">; // An option which is both joined to its (first) value, and followed by its // (second) value. def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">; +// An option which consumes all remaining arguments if there are any. +def KIND_REMAINING_ARGS : OptionKind<"RemainingArgs">; // Define the option flags. diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h index a5b59ce..5035940 100644 --- a/include/llvm/Option/OptTable.h +++ b/include/llvm/Option/OptTable.h @@ -51,6 +51,7 @@ private: /// \brief The static option information table. const Info *OptionInfos; unsigned NumOptionInfos; + bool IgnoreCase; unsigned TheInputOptionID; unsigned TheUnknownOptionID; @@ -72,7 +73,8 @@ private: } protected: - OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos); + OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos, + bool _IgnoreCase = false); public: ~OptTable(); diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h index 47fd817..03d4774 100644 --- a/include/llvm/Option/Option.h +++ b/include/llvm/Option/Option.h @@ -50,6 +50,7 @@ public: FlagClass, JoinedClass, SeparateClass, + RemainingArgsClass, CommaJoinedClass, MultiArgClass, JoinedOrSeparateClass, @@ -149,6 +150,7 @@ public: case SeparateClass: case MultiArgClass: case JoinedOrSeparateClass: + case RemainingArgsClass: return RenderSeparateStyle; } llvm_unreachable("Unexpected kind!"); diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h index b6a8186..2a191b3 100644 --- a/include/llvm/PassManager.h +++ b/include/llvm/PassManager.h @@ -7,101 +7,33 @@ // //===----------------------------------------------------------------------===// // -// This file defines the PassManager class. This class is used to hold, -// maintain, and optimize execution of Passes. The PassManager class ensures -// that analysis results are available before a pass runs, and that Pass's are -// destroyed when the PassManager is destroyed. +// This is a legacy redirect header for the old PassManager. It is intended to +// be used by clients that have not been converted to be aware of the new pass +// management infrastructure being built for LLVM, which is every client +// initially. Eventually this header (and the legacy management layer) will go +// away, but we want to minimize changes to out-of-tree users of LLVM in the +// interim. +// +// Note that this header *must not* be included into the same file as the new +// pass management infrastructure is included. Things will break spectacularly. +// If you are starting that conversion, you should switch to explicitly +// including LegacyPassManager.h and using the legacy namespace. // //===----------------------------------------------------------------------===// #ifndef LLVM_PASSMANAGER_H #define LLVM_PASSMANAGER_H -#include "llvm/Pass.h" -#include "llvm/Support/CBindingWrapping.h" +#include "llvm/IR/LegacyPassManager.h" namespace llvm { -class Pass; -class Module; - -class PassManagerImpl; -class FunctionPassManagerImpl; - -/// PassManagerBase - An abstract interface to allow code to add passes to -/// a pass manager without having to hard-code what kind of pass manager -/// it is. -class PassManagerBase { -public: - virtual ~PassManagerBase(); - - /// add - Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// implies that all passes MUST be allocated with 'new'. - virtual void add(Pass *P) = 0; -}; - -/// PassManager manages ModulePassManagers -class PassManager : public PassManagerBase { -public: - - PassManager(); - ~PassManager(); - - /// add - Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// implies that all passes MUST be allocated with 'new'. - void add(Pass *P); - - /// run - Execute all of the passes scheduled for execution. Keep track of - /// whether any of the passes modifies the module, and if so, return true. - bool run(Module &M); - -private: - /// PassManagerImpl_New is the actual class. PassManager is just the - /// wraper to publish simple pass manager interface - PassManagerImpl *PM; -}; - -/// FunctionPassManager manages FunctionPasses and BasicBlockPassManagers. -class FunctionPassManager : public PassManagerBase { -public: - /// FunctionPassManager ctor - This initializes the pass manager. It needs, - /// but does not take ownership of, the specified Module. - explicit FunctionPassManager(Module *M); - ~FunctionPassManager(); - - /// add - Add a pass to the queue of passes to run. This passes - /// ownership of the Pass to the PassManager. When the - /// PassManager_X is destroyed, the pass will be destroyed as well, so - /// there is no need to delete the pass. - /// This implies that all passes MUST be allocated with 'new'. - void add(Pass *P); - - /// run - Execute all of the passes scheduled for execution. Keep - /// track of whether any of the passes modifies the function, and if - /// so, return true. - /// - bool run(Function &F); - - /// doInitialization - Run all of the initializers for the function passes. - /// - bool doInitialization(); - - /// doFinalization - Run all of the finalizers for the function passes. - /// - bool doFinalization(); - -private: - FunctionPassManagerImpl *FPM; - Module *M; -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBase, LLVMPassManagerRef) +// Pull these into the llvm namespace so that existing code that expects it +// there can find it. +using legacy::PassManagerBase; +using legacy::PassManager; +using legacy::FunctionPassManager; -} // End llvm namespace +} #endif diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index 3243fd9..397f50f 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -99,6 +99,9 @@ class BumpPtrAllocator { /// allocate a separate slab. size_t SizeThreshold; + /// \brief the default allocator used if one is not provided + MallocSlabAllocator DefaultSlabAllocator; + /// Allocator - The underlying allocator we use to get slabs of memory. This /// defaults to MallocSlabAllocator, which wraps malloc, but it could be /// changed to use a custom allocator. @@ -133,12 +136,10 @@ class BumpPtrAllocator { /// one. void DeallocateSlabs(MemSlab *Slab); - static MallocSlabAllocator DefaultSlabAllocator; - template<typename T> friend class SpecificBumpPtrAllocator; public: - BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, - SlabAllocator &allocator = DefaultSlabAllocator); + BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096); + BumpPtrAllocator(size_t size, size_t threshold, SlabAllocator &allocator); ~BumpPtrAllocator(); /// Reset - Deallocate all but the current slab and reset the current pointer @@ -189,8 +190,10 @@ template <typename T> class SpecificBumpPtrAllocator { BumpPtrAllocator Allocator; public: - SpecificBumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, - SlabAllocator &allocator = BumpPtrAllocator::DefaultSlabAllocator) + SpecificBumpPtrAllocator(size_t size = 4096, size_t threshold = 4096) + : Allocator(size, threshold) {} + SpecificBumpPtrAllocator(size_t size, size_t threshold, + SlabAllocator &allocator) : Allocator(size, threshold, allocator) {} ~SpecificBumpPtrAllocator() { diff --git a/include/llvm/Support/BlockFrequency.h b/include/llvm/Support/BlockFrequency.h index 666b3c8..21879e7 100644 --- a/include/llvm/Support/BlockFrequency.h +++ b/include/llvm/Support/BlockFrequency.h @@ -27,8 +27,10 @@ class BlockFrequency { uint64_t Frequency; static const int64_t ENTRY_FREQ = 1 << 14; - // Scale frequency by N/D, saturating on overflow. - void scale(uint32_t N, uint32_t D); + /// \brief Scale the given BlockFrequency by N/D. Return the remainder from + /// the division by D. Upon overflow, the routine will saturate and + /// additionally will return the remainder set to D. + uint32_t scale(uint32_t N, uint32_t D); public: BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { } @@ -57,6 +59,10 @@ public: BlockFrequency &operator+=(const BlockFrequency &Freq); const BlockFrequency operator+(const BlockFrequency &Freq) const; + /// \brief Scale the given BlockFrequency by N/D. Return the remainder from + /// the division by D. Upon overflow, the routine will saturate. + uint32_t scale(const BranchProbability &Prob); + bool operator<(const BlockFrequency &RHS) const { return Frequency < RHS.Frequency; } diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index a39a3f9..9cc3989 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -222,7 +222,7 @@ namespace COFF { uint32_t Characteristics; }; - enum SectionCharacteristics { + enum SectionCharacteristics LLVM_ENUM_INT_TYPE(uint32_t) { SC_Invalid = 0xffffffff, IMAGE_SCN_TYPE_NO_PAD = 0x00000008, @@ -511,7 +511,9 @@ namespace COFF { IMAGE_SUBSYSTEM_NATIVE = 1, ///< Device drivers and native Windows processes IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, ///< The Windows GUI subsystem. IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, ///< The Windows character subsystem. + IMAGE_SUBSYSTEM_OS2_CUI = 5, ///< The OS/2 character subsytem. IMAGE_SUBSYSTEM_POSIX_CUI = 7, ///< The POSIX character subsystem. + IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8, ///< Native Windows 9x driver. IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, ///< Windows CE. IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, ///< An EFI application. IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, ///< An EFI driver with boot @@ -519,7 +521,8 @@ namespace COFF { IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, ///< An EFI driver with run-time /// services. IMAGE_SUBSYSTEM_EFI_ROM = 13, ///< An EFI ROM image. - IMAGE_SUBSYSTEM_XBOX = 14 ///< XBOX. + IMAGE_SUBSYSTEM_XBOX = 14, ///< XBOX. + IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16 ///< A BCD application. }; enum DLLCharacteristics { diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index c0bfbae..4efb6a6 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -350,6 +350,9 @@ struct cat { struct GenericOptionValue { virtual ~GenericOptionValue() {} virtual bool compare(const GenericOptionValue &V) const = 0; + +private: + virtual void anchor(); }; template<class DataType> struct OptionValue; @@ -1752,6 +1755,7 @@ void getRegisteredOptions(StringMap<Option*> &Map); /// \brief Saves strings in the inheritor's stable storage and returns a stable /// raw character pointer. class StringSaver { + virtual void anchor(); public: virtual const char *SaveString(const char *Str) = 0; virtual ~StringSaver() {}; // Pacify -Wnon-virtual-dtor. diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index feac934..860f43e 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -179,6 +179,12 @@ #define LLVM_ATTRIBUTE_USED #endif +#if __has_attribute(warn_unused_result) || __GNUC_PREREQ(3, 4) +#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#else +#define LLVM_ATTRIBUTE_UNUSED_RESULT +#endif + // Some compilers warn about unused functions. When a function is sometimes // used or not depending on build settings (e.g. a function only called from // within "assert"), this attribute can be used to suppress such warnings. @@ -385,4 +391,24 @@ # define LLVM_STATIC_ASSERT(expr, msg) #endif +/// \macro LLVM_ENUM_INT_TYPE +/// \brief Expands to colon followed by the given integral type on compilers +/// which support C++11 strong enums. This can be used to make enums unsigned +/// with MSVC. +#if __has_feature(cxx_strong_enums) +# define LLVM_ENUM_INT_TYPE(intty) : intty +#elif defined(_MSC_VER) && _MSC_VER >= 1600 // Added in MSVC 2010. +# define LLVM_ENUM_INT_TYPE(intty) : intty +#else +# define LLVM_ENUM_INT_TYPE(intty) +#endif + +/// \brief Does the compiler support generalized initializers (using braced +/// lists and std::initializer_list). +#if __has_feature(cxx_generalized_initializers) +#define LLVM_HAS_INITIALIZER_LISTS 1 +#else +#define LLVM_HAS_INITIALIZER_LISTS 0 +#endif + #endif diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h index 9b1142d..bef9146 100644 --- a/include/llvm/Support/Compression.h +++ b/include/llvm/Support/Compression.h @@ -50,6 +50,8 @@ Status uncompress(StringRef InputBuffer, OwningPtr<MemoryBuffer> &UncompressedBuffer, size_t UncompressedSize); +uint32_t crc32(StringRef Buffer); + } // End of namespace zlib } // End of namespace llvm diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index 896fe84..2702408 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -26,9 +26,9 @@ #ifndef LLVM_SUPPORT_DEBUG_H #define LLVM_SUPPORT_DEBUG_H -namespace llvm { +#include "llvm/Support/raw_ostream.h" -class raw_ostream; +namespace llvm { /// DEBUG_TYPE macro - Files can specify a DEBUG_TYPE as a string, which causes /// all of their DEBUG statements to be activatable with -debug-only=thatstring. diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/Support/DebugLoc.h index f35d407..05f31d7 100644 --- a/include/llvm/Support/DebugLoc.h +++ b/include/llvm/Support/DebugLoc.h @@ -15,6 +15,8 @@ #ifndef LLVM_SUPPORT_DEBUGLOC_H #define LLVM_SUPPORT_DEBUGLOC_H +#include "llvm/Support/DataTypes.h"
+ namespace llvm { template <typename T> struct DenseMapInfo; class MDNode; @@ -45,7 +47,7 @@ namespace llvm { /// LineCol - This 32-bit value encodes the line and column number for the /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 /// for either means unknown. - unsigned LineCol; + uint32_t LineCol; /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, /// decoded by LLVMContext. 0 is unknown. diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index d0e2322..23bbd1c 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -16,60 +16,59 @@ #ifndef LLVM_SUPPORT_DWARF_H #define LLVM_SUPPORT_DWARF_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" - namespace llvm { //===----------------------------------------------------------------------===// // Debug info constants. -enum { - LLVMDebugVersion = (12 << 16), // Current version of debug information. - LLVMDebugVersion11 = (11 << 16), // Constant for version 11. - LLVMDebugVersion10 = (10 << 16), // Constant for version 10. - LLVMDebugVersion9 = (9 << 16), // Constant for version 9. - LLVMDebugVersion8 = (8 << 16), // Constant for version 8. - LLVMDebugVersion7 = (7 << 16), // Constant for version 7. - LLVMDebugVersion6 = (6 << 16), // Constant for version 6. - LLVMDebugVersion5 = (5 << 16), // Constant for version 5. - LLVMDebugVersion4 = (4 << 16), // Constant for version 4. - LLVMDebugVersionMask = 0xffff0000 // Mask for version number. +enum LLVM_ENUM_INT_TYPE(uint32_t) { + LLVMDebugVersion = (12 << 16), // Current version of debug information. + LLVMDebugVersion11 = (11 << 16), // Constant for version 11. + LLVMDebugVersion10 = (10 << 16), // Constant for version 10. + LLVMDebugVersion9 = (9 << 16), // Constant for version 9. + LLVMDebugVersion8 = (8 << 16), // Constant for version 8. + LLVMDebugVersion7 = (7 << 16), // Constant for version 7. + LLVMDebugVersion6 = (6 << 16), // Constant for version 6. + LLVMDebugVersion5 = (5 << 16), // Constant for version 5. + LLVMDebugVersion4 = (4 << 16), // Constant for version 4. + LLVMDebugVersionMask = 0xffff0000 // Mask for version number. }; namespace dwarf { //===----------------------------------------------------------------------===// // Dwarf constants as gleaned from the DWARF Debugging Information Format V.4 -// reference manual http://dwarf.freestandards.org . +// reference manual http://dwarf.freestandards.org. // // Do not mix the following two enumerations sets. DW_TAG_invalid changes the // enumeration base type. -enum llvm_dwarf_constants { +enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { // llvm mock tags - DW_TAG_invalid = ~0U, // Tag for invalid results. + DW_TAG_invalid = ~0U, // Tag for invalid results. - DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. - DW_TAG_arg_variable = 0x101, // Tag for argument variables. + DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. + DW_TAG_arg_variable = 0x101, // Tag for argument variables. - DW_TAG_user_base = 0x1000, // Recommended base for user tags. + DW_TAG_user_base = 0x1000, // Recommended base for user tags. - DW_CIE_VERSION = 1 // Common frame information version. + DWARF_VERSION = 4, // Default dwarf version we output. + DW_CIE_VERSION = 1, // Common frame information version. + DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. + DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. + DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges. }; - // Special ID values that distinguish a CIE from a FDE in DWARF CFI. // Not inside an enum because a 64-bit value is needed. const uint32_t DW_CIE_ID = UINT32_MAX; const uint64_t DW64_CIE_ID = UINT64_MAX; - -enum dwarf_constants { - DWARF_VERSION = 2, - - // Tags +enum Tag LLVM_ENUM_INT_TYPE(uint16_t) { DW_TAG_array_type = 0x01, DW_TAG_class_type = 0x02, DW_TAG_entry_point = 0x03, @@ -139,12 +138,38 @@ enum dwarf_constants { DW_TAG_GNU_formal_parameter_pack = 0x4108, DW_TAG_lo_user = 0x4080, DW_TAG_APPLE_property = 0x4200, - DW_TAG_hi_user = 0xffff, - - // Children flag - DW_CHILDREN_no = 0x00, - DW_CHILDREN_yes = 0x01, + DW_TAG_hi_user = 0xffff +}; +inline bool isType(Tag T) { + switch (T) { + case DW_TAG_array_type: + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_enumeration_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + case DW_TAG_string_type: + case DW_TAG_structure_type: + case DW_TAG_subroutine_type: + case DW_TAG_union_type: + case DW_TAG_ptr_to_member_type: + case DW_TAG_set_type: + case DW_TAG_subrange_type: + case DW_TAG_base_type: + case DW_TAG_const_type: + case DW_TAG_file_type: + case DW_TAG_packed_type: + case DW_TAG_volatile_type: + case DW_TAG_typedef: + return true; + default: + return false; + } +} + +enum Attribute LLVM_ENUM_INT_TYPE(uint16_t) { // Attributes DW_AT_sibling = 0x01, DW_AT_location = 0x02, @@ -295,8 +320,10 @@ enum dwarf_constants { DW_AT_APPLE_property_setter = 0x3fea, DW_AT_APPLE_property_attribute = 0x3feb, DW_AT_APPLE_objc_complete_type = 0x3fec, - DW_AT_APPLE_property = 0x3fed, + DW_AT_APPLE_property = 0x3fed +}; +enum Form LLVM_ENUM_INT_TYPE(uint16_t) { // Attribute form encodings DW_FORM_addr = 0x01, DW_FORM_block2 = 0x03, @@ -326,8 +353,10 @@ enum dwarf_constants { // Extensions for Fission proposal DW_FORM_GNU_addr_index = 0x1f01, - DW_FORM_GNU_str_index = 0x1f02, + DW_FORM_GNU_str_index = 0x1f02 +}; +enum LocationAtom { // Operation encodings DW_OP_addr = 0x03, DW_OP_deref = 0x06, @@ -486,10 +515,15 @@ enum dwarf_constants { DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, + // Extensions for GNU-style thread-local storage. + DW_OP_GNU_push_tls_address = 0xe0, + // Extensions for Fission proposal. DW_OP_GNU_addr_index = 0xfb, - DW_OP_GNU_const_index = 0xfc, + DW_OP_GNU_const_index = 0xfc +}; +enum TypeKind { // Encoding attribute values DW_ATE_address = 0x01, DW_ATE_boolean = 0x02, @@ -508,37 +542,49 @@ enum dwarf_constants { DW_ATE_decimal_float = 0x0f, DW_ATE_UTF = 0x10, DW_ATE_lo_user = 0x80, - DW_ATE_hi_user = 0xff, + DW_ATE_hi_user = 0xff +}; +enum DecimalSignEncoding { // Decimal sign attribute values DW_DS_unsigned = 0x01, DW_DS_leading_overpunch = 0x02, DW_DS_trailing_overpunch = 0x03, DW_DS_leading_separate = 0x04, - DW_DS_trailing_separate = 0x05, + DW_DS_trailing_separate = 0x05 +}; +enum EndianityEncoding { // Endianity attribute values DW_END_default = 0x00, DW_END_big = 0x01, DW_END_little = 0x02, DW_END_lo_user = 0x40, - DW_END_hi_user = 0xff, + DW_END_hi_user = 0xff +}; +enum AccessAttribute { // Accessibility codes DW_ACCESS_public = 0x01, DW_ACCESS_protected = 0x02, - DW_ACCESS_private = 0x03, + DW_ACCESS_private = 0x03 +}; +enum VisibilityAttribute { // Visibility codes DW_VIS_local = 0x01, DW_VIS_exported = 0x02, - DW_VIS_qualified = 0x03, + DW_VIS_qualified = 0x03 +}; +enum VirtualityAttribute { // Virtuality codes DW_VIRTUALITY_none = 0x00, DW_VIRTUALITY_virtual = 0x01, - DW_VIRTUALITY_pure_virtual = 0x02, + DW_VIRTUALITY_pure_virtual = 0x02 +}; +enum SourceLanguage { // Language names DW_LANG_C89 = 0x0001, DW_LANG_C = 0x0002, @@ -562,35 +608,47 @@ enum dwarf_constants { DW_LANG_Python = 0x0014, DW_LANG_lo_user = 0x8000, DW_LANG_Mips_Assembler = 0x8001, - DW_LANG_hi_user = 0xffff, + DW_LANG_hi_user = 0xffff +}; +enum CaseSensitivity { // Identifier case codes DW_ID_case_sensitive = 0x00, DW_ID_up_case = 0x01, DW_ID_down_case = 0x02, - DW_ID_case_insensitive = 0x03, + DW_ID_case_insensitive = 0x03 +}; +enum CallingConvention { // Calling convention codes DW_CC_normal = 0x01, DW_CC_program = 0x02, DW_CC_nocall = 0x03, DW_CC_lo_user = 0x40, - DW_CC_hi_user = 0xff, + DW_CC_hi_user = 0xff +}; +enum InlineAttribute { // Inline codes DW_INL_not_inlined = 0x00, DW_INL_inlined = 0x01, DW_INL_declared_not_inlined = 0x02, - DW_INL_declared_inlined = 0x03, + DW_INL_declared_inlined = 0x03 +}; +enum ArrayDimensionOrdering { // Array ordering DW_ORD_row_major = 0x00, - DW_ORD_col_major = 0x01, + DW_ORD_col_major = 0x01 +}; +enum DiscriminantList { // Discriminant descriptor values DW_DSC_label = 0x00, - DW_DSC_range = 0x01, + DW_DSC_range = 0x01 +}; +enum LineNumberOps { // Line Number Standard Opcode Encodings DW_LNS_extended_op = 0x00, DW_LNS_copy = 0x01, @@ -604,23 +662,29 @@ enum dwarf_constants { DW_LNS_fixed_advance_pc = 0x09, DW_LNS_set_prologue_end = 0x0a, DW_LNS_set_epilogue_begin = 0x0b, - DW_LNS_set_isa = 0x0c, + DW_LNS_set_isa = 0x0c +}; +enum LineNumberExtendedOps { // Line Number Extended Opcode Encodings DW_LNE_end_sequence = 0x01, DW_LNE_set_address = 0x02, DW_LNE_define_file = 0x03, DW_LNE_set_discriminator = 0x04, DW_LNE_lo_user = 0x80, - DW_LNE_hi_user = 0xff, + DW_LNE_hi_user = 0xff +}; +enum MacinfoRecordType { // Macinfo Type Encodings DW_MACINFO_define = 0x01, DW_MACINFO_undef = 0x02, DW_MACINFO_start_file = 0x03, DW_MACINFO_end_file = 0x04, - DW_MACINFO_vendor_ext = 0xff, + DW_MACINFO_vendor_ext = 0xff +}; +enum CallFrameInfo { // Call frame instruction encodings DW_CFA_extended = 0x00, DW_CFA_nop = 0x00, @@ -653,7 +717,13 @@ enum dwarf_constants { DW_CFA_GNU_window_save = 0x2d, DW_CFA_GNU_args_size = 0x2e, DW_CFA_lo_user = 0x1c, - DW_CFA_hi_user = 0x3f, + DW_CFA_hi_user = 0x3f +}; + +enum Constants { + // Children flag + DW_CHILDREN_no = 0x00, + DW_CHILDREN_yes = 0x01, DW_EH_PE_absptr = 0x00, DW_EH_PE_omit = 0xff, @@ -671,8 +741,10 @@ enum dwarf_constants { DW_EH_PE_datarel = 0x30, DW_EH_PE_funcrel = 0x40, DW_EH_PE_aligned = 0x50, - DW_EH_PE_indirect = 0x80, + DW_EH_PE_indirect = 0x80 +}; +enum ApplePropertyAttributes { // Apple Objective-C Property Attributes DW_APPLE_PROPERTY_readonly = 0x01, DW_APPLE_PROPERTY_readwrite = 0x02, @@ -765,6 +837,84 @@ const char *MacinfoString(unsigned Encoding); /// CallFrameString - Return the string for the specified call frame instruction /// encodings. const char *CallFrameString(unsigned Encoding); + +// Constants for the DWARF5 Accelerator Table Proposal +enum AcceleratorTable { + // Data layout descriptors. + DW_ATOM_null = 0u, // Marker as the end of a list of atoms. + DW_ATOM_die_offset = 1u, // DIE offset in the debug_info section. + DW_ATOM_cu_offset = 2u, // Offset of the compile unit header that contains the + // item in question. + DW_ATOM_die_tag = 3u, // A tag entry. + DW_ATOM_type_flags = 4u, // Set of flags for a type. + + // DW_ATOM_type_flags values. + + // Always set for C++, only set for ObjC if this is the @implementation for a + // class. + DW_FLAG_type_implementation = 2u, + + // Hash functions. + + // Daniel J. Bernstein hash. + DW_hash_function_djb = 0u +}; + +/// AtomTypeString - Return the string for the specified Atom type. +const char *AtomTypeString(unsigned Atom); + +// Constants for the GNU pubnames/pubtypes extensions supporting gdb index. +enum GDBIndexEntryKind { + GIEK_NONE, + GIEK_TYPE, + GIEK_VARIABLE, + GIEK_FUNCTION, + GIEK_OTHER, + GIEK_UNUSED5, + GIEK_UNUSED6, + GIEK_UNUSED7 +}; + +const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind); + +enum GDBIndexEntryLinkage { + GIEL_EXTERNAL, + GIEL_STATIC +}; + +const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); + +/// The gnu_pub* kind looks like: +/// +/// 0-3 reserved +/// 4-6 symbol kind +/// 7 0 == global, 1 == static +/// +/// A gdb_index descriptor includes the above kind, shifted 24 bits up with the +/// offset of the cu within the debug_info section stored in those 24 bits. +struct PubIndexEntryDescriptor { + GDBIndexEntryKind Kind; + GDBIndexEntryLinkage Linkage; + PubIndexEntryDescriptor(GDBIndexEntryKind Kind, GDBIndexEntryLinkage Linkage) + : Kind(Kind), Linkage(Linkage) {} + /* implicit */ PubIndexEntryDescriptor(GDBIndexEntryKind Kind) + : Kind(Kind), Linkage(GIEL_EXTERNAL) {} + explicit PubIndexEntryDescriptor(uint8_t Value) + : Kind(static_cast<GDBIndexEntryKind>((Value & KIND_MASK) >> + KIND_OFFSET)), + Linkage(static_cast<GDBIndexEntryLinkage>((Value & LINKAGE_MASK) >> + LINKAGE_OFFSET)) {} + uint8_t toBits() { return Kind << KIND_OFFSET | Linkage << LINKAGE_OFFSET; } + +private: + enum { + KIND_OFFSET = 4, + KIND_MASK = 7 << KIND_OFFSET, + LINKAGE_OFFSET = 7, + LINKAGE_MASK = 1 << LINKAGE_OFFSET + }; +}; + } // End of namespace dwarf } // End of namespace llvm diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 54da31c..2868f35 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -20,6 +20,7 @@ #ifndef LLVM_SUPPORT_ELF_H #define LLVM_SUPPORT_ELF_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <cstring> @@ -650,7 +651,7 @@ enum { }; // ARM Specific e_flags -enum { +enum LLVM_ENUM_INT_TYPE(unsigned) { EF_ARM_SOFT_FLOAT = 0x00000200U, EF_ARM_VFP_FLOAT = 0x00000400U, EF_ARM_EABI_UNKNOWN = 0x00000000U, @@ -800,7 +801,7 @@ enum { }; // Mips Specific e_flags -enum { +enum LLVM_ENUM_INT_TYPE(unsigned) { EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions EF_MIPS_PIC = 0x00000002, // Position independent code EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code @@ -880,6 +881,19 @@ enum { R_MIPS_GLOB_DAT = 51, R_MIPS_COPY = 126, R_MIPS_JUMP_SLOT = 127, + R_MICROMIPS_26_S1 = 133, + R_MICROMIPS_HI16 = 134, + R_MICROMIPS_LO16 = 135, + R_MICROMIPS_GOT16 = 138, + R_MICROMIPS_PC16_S1 = 141, + R_MICROMIPS_CALL16 = 142, + R_MICROMIPS_GOT_DISP = 145, + R_MICROMIPS_GOT_PAGE = 146, + R_MICROMIPS_GOT_OFST = 147, + R_MICROMIPS_TLS_DTPREL_HI16 = 164, + R_MICROMIPS_TLS_DTPREL_LO16 = 165, + R_MICROMIPS_TLS_TPREL_HI16 = 169, + R_MICROMIPS_TLS_TPREL_LO16 = 170, R_MIPS_NUM = 218 }; @@ -1116,7 +1130,7 @@ enum { }; // Section types. -enum { +enum LLVM_ENUM_INT_TYPE(unsigned) { SHT_NULL = 0, // No associated section (inactive entry). SHT_PROGBITS = 1, // Program-defined contents. SHT_SYMTAB = 2, // Symbol table. @@ -1164,7 +1178,7 @@ enum { }; // Section flags. -enum { +enum LLVM_ENUM_INT_TYPE(unsigned) { // Section data should be writable during execution. SHF_WRITE = 0x1, @@ -1196,6 +1210,9 @@ enum { // This section holds Thread-Local Storage. SHF_TLS = 0x400U, + // This section is excluded from the final executable or shared library. + SHF_EXCLUDE = 0x80000000U, + // Start of target-specific flags. /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped @@ -1226,12 +1243,34 @@ enum { // for faster accesses SHF_HEX_GPREL = 0x10000000, - // Do not strip this section. FIXME: We need target specific SHF_ enums. - SHF_MIPS_NOSTRIP = 0x8000000 + // Section contains text/data which may be replicated in other sections. + // Linker must retain only one copy. + SHF_MIPS_NODUPES = 0x01000000, + + // Linker must generate implicit hidden weak names. + SHF_MIPS_NAMES = 0x02000000, + + // Section data local to process. + SHF_MIPS_LOCAL = 0x04000000, + + // Do not strip this section. + SHF_MIPS_NOSTRIP = 0x08000000, + + // Section must be part of global data area. + SHF_MIPS_GPREL = 0x10000000, + + // This section should be merged. + SHF_MIPS_MERGE = 0x20000000, + + // Address size to be inferred from section entry size. + SHF_MIPS_ADDR = 0x40000000, + + // Section data is string data by default. + SHF_MIPS_STRING = 0x80000000 }; // Section Group Flags -enum { +enum LLVM_ENUM_INT_TYPE(unsigned) { GRP_COMDAT = 0x1, GRP_MASKOS = 0x0ff00000, GRP_MASKPROC = 0xf0000000 @@ -1444,11 +1483,16 @@ enum { PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info // These all contain stack unwind tables. PT_ARM_EXIDX = 0x70000001, - PT_ARM_UNWIND = 0x70000001 + PT_ARM_UNWIND = 0x70000001, + + // MIPS program header types. + PT_MIPS_REGINFO = 0x70000000, // Register usage information. + PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. + PT_MIPS_OPTIONS = 0x70000002 // Options segment. }; // Segment flag bits. -enum { +enum LLVM_ENUM_INT_TYPE(unsigned) { PF_X = 1, // Execute PF_W = 2, // Write PF_R = 4, // Read @@ -1526,6 +1570,7 @@ enum { DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1. + DT_VERSYM = 0x6FFFFFF0, // The address of .gnu.version section. DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table. DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF. DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table. diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index f3ac305..d5b11cb 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -27,38 +27,6 @@ #endif namespace llvm { -struct ErrorHolderBase { - error_code Error; - uint16_t RefCount; - bool HasUserData; - - ErrorHolderBase() : RefCount(1) {} - - void aquire() { - ++RefCount; - } - - void release() { - if (--RefCount == 0) - delete this; - } - -protected: - virtual ~ErrorHolderBase() {} -}; - -template<class T> -struct ErrorHolder : ErrorHolderBase { -#if LLVM_HAS_RVALUE_REFERENCES - ErrorHolder(T &&UD) : UserData(llvm_move(UD)) {} -#else - ErrorHolder(T &UD) : UserData(UD) {} -#endif - T UserData; -}; - -template<class Tp> struct ErrorOrUserDataTraits : llvm::false_type {}; - #if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES template<class T, class V> typename std::enable_if< std::is_constructible<T, V>::value @@ -111,44 +79,6 @@ public: /// buffer->write("adena"); /// \endcode /// -/// ErrorOr<T> also supports user defined data for specific error_codes. To use -/// this feature you must first add a template specialization of -/// ErrorOrUserDataTraits derived from std::true_type for your type in the lld -/// namespace. This specialization must have a static error_code error() -/// function that returns the error_code this data is used with. -/// -/// getError<UserData>() may be called to get either the stored user data, or -/// a default constructed UserData if none was stored. -/// -/// Example: -/// \code -/// struct InvalidArgError { -/// InvalidArgError() {} -/// InvalidArgError(std::string S) : ArgName(S) {} -/// std::string ArgName; -/// }; -/// -/// namespace llvm { -/// template<> -/// struct ErrorOrUserDataTraits<InvalidArgError> : std::true_type { -/// static error_code error() { -/// return make_error_code(errc::invalid_argument); -/// } -/// }; -/// } // end namespace llvm -/// -/// using namespace llvm; -/// -/// ErrorOr<int> foo() { -/// return InvalidArgError("adena"); -/// } -/// -/// int main() { -/// auto a = foo(); -/// if (!a && error_code(a) == errc::invalid_argument) -/// llvm::errs() << a.getError<InvalidArgError>().ArgName << "\n"; -/// } -/// \endcode /// /// An implicit conversion to bool provides a way to check if there was an /// error. The unary * and -> operators provide pointer like access to the @@ -178,43 +108,28 @@ private: typedef typename remove_reference<T>::type *pointer; public: - ErrorOr() : IsValid(false) {} - template <class E> ErrorOr(E ErrorCode, typename enable_if_c<is_error_code_enum<E>::value || is_error_condition_enum<E>::value, void *>::type = 0) - : HasError(true), IsValid(true) { - Error = new ErrorHolderBase; - Error->Error = make_error_code(ErrorCode); - Error->HasUserData = false; - } - - ErrorOr(llvm::error_code EC) : HasError(true), IsValid(true) { - Error = new ErrorHolderBase; - Error->Error = EC; - Error->HasUserData = false; + : HasError(true) { + new (getError()) error_code(make_error_code(ErrorCode)); } - template<class UserDataT> - ErrorOr(UserDataT UD, typename - enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0) - : HasError(true), IsValid(true) { - Error = new ErrorHolder<UserDataT>(llvm_move(UD)); - Error->Error = ErrorOrUserDataTraits<UserDataT>::error(); - Error->HasUserData = true; + ErrorOr(llvm::error_code EC) : HasError(true) { + new (getError()) error_code(EC); } - ErrorOr(T Val) : HasError(false), IsValid(true) { + ErrorOr(T Val) : HasError(false) { new (get()) storage_type(moveIfMoveConstructible<storage_type>(Val)); } - ErrorOr(const ErrorOr &Other) : IsValid(false) { + ErrorOr(const ErrorOr &Other) { copyConstruct(Other); } template <class OtherT> - ErrorOr(const ErrorOr<OtherT> &Other) : IsValid(false) { + ErrorOr(const ErrorOr<OtherT> &Other) { copyConstruct(Other); } @@ -230,12 +145,12 @@ public: } #if LLVM_HAS_RVALUE_REFERENCES - ErrorOr(ErrorOr &&Other) : IsValid(false) { + ErrorOr(ErrorOr &&Other) { moveConstruct(std::move(Other)); } template <class OtherT> - ErrorOr(ErrorOr<OtherT> &&Other) : IsValid(false) { + ErrorOr(ErrorOr<OtherT> &&Other) { moveConstruct(std::move(Other)); } @@ -252,37 +167,20 @@ public: #endif ~ErrorOr() { - if (!IsValid) - return; - if (HasError) - Error->release(); - else + if (!HasError) get()->~storage_type(); } - template<class ET> - ET getError() const { - assert(IsValid && "Cannot get the error of a default constructed ErrorOr!"); - assert(HasError && "Cannot get an error if none exists!"); - assert(ErrorOrUserDataTraits<ET>::error() == Error->Error && - "Incorrect user error data type for error!"); - if (!Error->HasUserData) - return ET(); - return reinterpret_cast<const ErrorHolder<ET>*>(Error)->UserData; - } - typedef void (*unspecified_bool_type)(); static void unspecified_bool_true() {} /// \brief Return false if there is an error. operator unspecified_bool_type() const { - assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); return HasError ? 0 : unspecified_bool_true; } operator llvm::error_code() const { - assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); - return HasError ? Error->Error : llvm::error_code::success(); + return HasError ? *getError() : llvm::error_code::success(); } pointer operator ->() { @@ -296,19 +194,14 @@ public: private: template <class OtherT> void copyConstruct(const ErrorOr<OtherT> &Other) { - // Construct an invalid ErrorOr if other is invalid. - if (!Other.IsValid) - return; - IsValid = true; if (!Other.HasError) { // Get the other value. HasError = false; new (get()) storage_type(*Other.get()); } else { // Get other's error. - Error = Other.Error; HasError = true; - Error->aquire(); + new (getError()) error_code(Other); } } @@ -334,22 +227,14 @@ private: #if LLVM_HAS_RVALUE_REFERENCES template <class OtherT> void moveConstruct(ErrorOr<OtherT> &&Other) { - // Construct an invalid ErrorOr if other is invalid. - if (!Other.IsValid) - return; - IsValid = true; if (!Other.HasError) { // Get the other value. HasError = false; new (get()) storage_type(std::move(*Other.get())); - // Tell other not to do any destruction. - Other.IsValid = false; } else { // Get other's error. - Error = Other.Error; HasError = true; - // Tell other not to do any destruction. - Other.IsValid = false; + new (getError()) error_code(Other); } } @@ -372,135 +257,30 @@ private: } storage_type *get() { - assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast<storage_type*>(TStorage.buffer); } const storage_type *get() const { - assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast<const storage_type*>(TStorage.buffer); } - union { - AlignedCharArrayUnion<storage_type> TStorage; - ErrorHolderBase *Error; - }; - bool HasError : 1; - bool IsValid : 1; -}; - -// ErrorOr specialization for void. -template <> -class ErrorOr<void> { -public: - ErrorOr() : Error(0, 0) {} - - template <class E> - ErrorOr(E ErrorCode, typename enable_if_c<is_error_code_enum<E>::value || - is_error_condition_enum<E>::value, - void *> ::type = 0) - : Error(0, 0) { - error_code EC = make_error_code(ErrorCode); - if (EC == errc::success) { - Error.setInt(1); - return; - } - ErrorHolderBase *EHB = new ErrorHolderBase; - EHB->Error = EC; - EHB->HasUserData = false; - Error.setPointer(EHB); - } - - ErrorOr(llvm::error_code EC) : Error(0, 0) { - if (EC == errc::success) { - Error.setInt(1); - return; - } - ErrorHolderBase *E = new ErrorHolderBase; - E->Error = EC; - E->HasUserData = false; - Error.setPointer(E); - } - - template<class UserDataT> - ErrorOr(UserDataT UD, typename - enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0) - : Error(0, 0) { - ErrorHolderBase *E = new ErrorHolder<UserDataT>(llvm_move(UD)); - E->Error = ErrorOrUserDataTraits<UserDataT>::error(); - E->HasUserData = true; - Error.setPointer(E); + error_code *getError() { + assert(HasError && "Cannot get error when a value exists!"); + return reinterpret_cast<error_code*>(ErrorStorage.buffer); } - ErrorOr(const ErrorOr &Other) : Error(0, 0) { - Error = Other.Error; - if (Other.Error.getPointer()->Error) { - Error.getPointer()->aquire(); - } + const error_code *getError() const { + return const_cast<ErrorOr<T> *>(this)->getError(); } - ErrorOr &operator =(const ErrorOr &Other) { - if (this == &Other) - return *this; - - this->~ErrorOr(); - new (this) ErrorOr(Other); - return *this; - } - -#if LLVM_HAS_RVALUE_REFERENCES - ErrorOr(ErrorOr &&Other) : Error(0) { - // Get other's error. - Error = Other.Error; - // Tell other not to do any destruction. - Other.Error.setPointer(0); - } - - ErrorOr &operator =(ErrorOr &&Other) { - if (this == &Other) - return *this; - - this->~ErrorOr(); - new (this) ErrorOr(std::move(Other)); - - return *this; - } -#endif - - ~ErrorOr() { - if (Error.getPointer()) - Error.getPointer()->release(); - } - - template<class ET> - ET getError() const { - assert(ErrorOrUserDataTraits<ET>::error() == *this && - "Incorrect user error data type for error!"); - if (!Error.getPointer()->HasUserData) - return ET(); - return reinterpret_cast<const ErrorHolder<ET> *>( - Error.getPointer())->UserData; - } - - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - - /// \brief Return false if there is an error. - operator unspecified_bool_type() const { - return Error.getInt() ? unspecified_bool_true : 0; - } - - operator llvm::error_code() const { - return Error.getInt() ? make_error_code(errc::success) - : Error.getPointer()->Error; - } - -private: - // If the bit is 1, the error is success. - llvm::PointerIntPair<ErrorHolderBase *, 1> Error; + union { + AlignedCharArrayUnion<storage_type> TStorage; + AlignedCharArrayUnion<error_code> ErrorStorage; + }; + bool HasError : 1; }; template<class T, class E> diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index c130b47..d301f84 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -238,7 +238,9 @@ struct file_magic { macho_dsym_companion, ///< Mach-O dSYM companion file macho_universal_binary, ///< Mach-O universal binary coff_object, ///< COFF object file - pecoff_executable ///< PECOFF executable file + coff_import_library, ///< COFF import library + pecoff_executable, ///< PECOFF executable file + windows_resource ///< Windows compiled resource file (.rc) }; bool is_object() const { @@ -638,17 +640,6 @@ error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, error_code openFileForRead(const Twine &Name, int &ResultFD); -/// @brief Canonicalize path. -/// -/// Sets result to the file system's idea of what path is. The result is always -/// absolute and has the same capitalization as the file system. -/// -/// @param path Input path. -/// @param result Set to the canonicalized version of \a path. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); - /// @brief Are \a path's first bytes \a magic? /// /// @param path Input path. @@ -731,7 +722,7 @@ public: /// should begin. Must be a multiple of /// mapped_file_region::alignment(). /// \param ec This is set to errc::success if the map was constructed - /// sucessfully. Otherwise it is set to a platform dependent error. + /// successfully. Otherwise it is set to a platform dependent error. mapped_file_region(const Twine &path, mapmode mode, uint64_t length, @@ -869,7 +860,7 @@ public: } /// Construct end iterator. - directory_iterator() : State(new detail::DirIterState) {} + directory_iterator() : State(0) {} // No operator++ because we need error_code. directory_iterator &increment(error_code &ec) { @@ -881,6 +872,12 @@ public: const directory_entry *operator->() const { return &State->CurrentEntry; } bool operator==(const directory_iterator &RHS) const { + if (State == RHS.State) + return true; + if (RHS.State == 0) + return State->CurrentEntry == directory_entry(); + if (State == 0) + return RHS.State->CurrentEntry == directory_entry(); return State->CurrentEntry == RHS.State->CurrentEntry; } @@ -920,7 +917,7 @@ public: } // No operator++ because we need error_code. recursive_directory_iterator &increment(error_code &ec) { - static const directory_iterator end_itr; + const directory_iterator end_itr; if (State->HasNoPushRequest) State->HasNoPushRequest = false; @@ -964,10 +961,10 @@ public: // modifiers /// Goes up one level if Level > 0. void pop() { - assert(State && "Cannot pop and end itertor!"); + assert(State && "Cannot pop an end iterator!"); assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); - static const directory_iterator end_itr; + const directory_iterator end_itr; error_code ec; do { if (ec) diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 18ee048..df1f218 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -129,6 +129,27 @@ public: /// getLine - Return the line number unsigned getLine() { return Position.second; } + + raw_ostream &resetColor() { + TheStream->resetColor(); + return *this; + } + + raw_ostream &reverseColor() { + TheStream->reverseColor(); + return *this; + } + + raw_ostream &changeColor(enum Colors Color, + bool Bold, + bool BG) { + TheStream->changeColor(Color, Bold, BG); + return *this; + } + + bool is_displayed() const { + return TheStream->is_displayed(); + } private: void releaseStream() { diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index f1040f5..0aa716a 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -15,6 +15,7 @@ #ifndef LLVM_SUPPORT_GCOV_H #define LLVM_SUPPORT_GCOV_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/MemoryBuffer.h" @@ -24,7 +25,6 @@ namespace llvm { class GCOVFunction; class GCOVBlock; -class GCOVLines; class FileInfo; namespace GCOV { @@ -125,30 +125,65 @@ public: return true; } - uint32_t readInt() { - uint32_t Result; + /// readObjectTag - If cursor points to an object summary tag then increment + /// the cursor and return true otherwise return false. + bool readObjectTag() { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (Tag.empty() || + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\0' || Tag[3] != '\xa1') { + return false; + } + Cursor += 4; + return true; + } + + /// readProgramTag - If cursor points to a program summary tag then increment + /// the cursor and return true otherwise return false. + bool readProgramTag() { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (Tag.empty() || + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\0' || Tag[3] != '\xa3') { + return false; + } + Cursor += 4; + return true; + } + + bool readInt(uint32_t &Val) { + if (Buffer->getBuffer().size() < Cursor+4) { + errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n"; + return false; + } StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4); - assert (Str.empty() == false && "Unexpected memory buffer end!"); Cursor += 4; - Result = *(const uint32_t *)(Str.data()); - return Result; + Val = *(const uint32_t *)(Str.data()); + return true; } - uint64_t readInt64() { - uint64_t Lo = readInt(); - uint64_t Hi = readInt(); - uint64_t Result = Lo | (Hi << 32); - return Result; + bool readInt64(uint64_t &Val) { + uint32_t Lo, Hi; + if (!readInt(Lo) || !readInt(Hi)) return false; + Val = ((uint64_t)Hi << 32) | Lo; + return true; } - StringRef readString() { - uint32_t Len = readInt() * 4; - StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len); + bool readString(StringRef &Str) { + uint32_t Len; + if (!readInt(Len)) return false; + Len *= 4; + if (Buffer->getBuffer().size() < Cursor+Len) { + errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n"; + return false; + } + Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first; Cursor += Len; - return Str; + return true; } uint64_t getCursor() const { return Cursor; } + void advanceCursor(uint32_t n) { Cursor += n*4; } private: MemoryBuffer *Buffer; uint64_t Cursor; @@ -158,13 +193,15 @@ private: /// (.gcno and .gcda). class GCOVFile { public: - GCOVFile() {} + GCOVFile() : Functions(), RunCount(0), ProgramCount(0) {} ~GCOVFile(); bool read(GCOVBuffer &Buffer); void dump(); void collectLineCounts(FileInfo &FI); private: SmallVector<GCOVFunction *, 16> Functions; + uint32_t RunCount; + uint32_t ProgramCount; }; /// GCOVFunction - Collects function information. @@ -173,6 +210,7 @@ public: GCOVFunction() : Ident(0), LineNumber(0) {} ~GCOVFunction(); bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format); + StringRef getFilename() const { return Filename; } void dump(); void collectLineCounts(FileInfo &FI); private: @@ -186,39 +224,36 @@ private: /// GCOVBlock - Collects block information. class GCOVBlock { public: - GCOVBlock(uint32_t N) : Number(N), Counter(0) {} + GCOVBlock(GCOVFunction &P, uint32_t N) : + Parent(P), Number(N), Counter(0), Edges(), Lines() {} ~GCOVBlock(); void addEdge(uint32_t N) { Edges.push_back(N); } - void addLine(StringRef Filename, uint32_t LineNo); - void addCount(uint64_t N) { Counter = N; } + void addLine(uint32_t N) { Lines.push_back(N); } + void addCount(uint64_t N) { Counter += N; } + size_t getNumEdges() { return Edges.size(); } void dump(); void collectLineCounts(FileInfo &FI); private: + GCOVFunction &Parent; uint32_t Number; uint64_t Counter; SmallVector<uint32_t, 16> Edges; - StringMap<GCOVLines *> Lines; + SmallVector<uint32_t, 16> Lines; }; -/// GCOVLines - A wrapper around a vector of int to keep track of line nos. -class GCOVLines { -public: - ~GCOVLines() { Lines.clear(); } - void add(uint32_t N) { Lines.push_back(N); } - void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count); - void dump(); - -private: - SmallVector<uint32_t, 4> Lines; -}; - -typedef SmallVector<uint32_t, 16> LineCounts; +typedef DenseMap<uint32_t, uint64_t> LineCounts; class FileInfo { public: - void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count); - void print(); + void addLineCount(StringRef Filename, uint32_t Line, uint64_t Count) { + LineInfo[Filename][Line-1] += Count; + } + void setRunCount(uint32_t Runs) { RunCount = Runs; } + void setProgramCount(uint32_t Programs) { ProgramCount = Programs; } + void print(raw_fd_ostream &OS, StringRef gcnoFile, StringRef gcdaFile); private: StringMap<LineCounts> LineInfo; + uint32_t RunCount; + uint32_t ProgramCount; }; } diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h deleted file mode 100644 index 64b79ee..0000000 --- a/include/llvm/Support/IntegersSubset.h +++ /dev/null @@ -1,540 +0,0 @@ -//===-- llvm/IntegersSubset.h - The subset of integers ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// @file -/// This file contains class that implements constant set of ranges: -/// [<Low0,High0>,...,<LowN,HighN>]. Initially, this class was created for -/// SwitchInst and was used for case value representation that may contain -/// multiple ranges for a single successor. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_INTEGERSSUBSET_H -#define LLVM_SUPPORT_INTEGERSSUBSET_H - -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/LLVMContext.h" -#include <list> - -namespace llvm { - - // The IntItem is a wrapper for APInt. - // 1. It determines sign of integer, it allows to use - // comparison operators >,<,>=,<=, and as result we got shorter and cleaner - // constructions. - // 2. It helps to implement PR1255 (case ranges) as a series of small patches. - // 3. Currently we can interpret IntItem both as ConstantInt and as APInt. - // It allows to provide SwitchInst methods that works with ConstantInt for - // non-updated passes. And it allows to use APInt interface for new methods. - // 4. IntItem can be easily replaced with APInt. - - // The set of macros that allows to propagate APInt operators to the IntItem. - -#define INT_ITEM_DEFINE_COMPARISON(op,func) \ - bool operator op (const APInt& RHS) const { \ - return getAPIntValue().func(RHS); \ - } - -#define INT_ITEM_DEFINE_UNARY_OP(op) \ - IntItem operator op () const { \ - APInt res = op(getAPIntValue()); \ - Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ - return IntItem(cast<ConstantInt>(NewVal)); \ - } - -#define INT_ITEM_DEFINE_BINARY_OP(op) \ - IntItem operator op (const APInt& RHS) const { \ - APInt res = getAPIntValue() op RHS; \ - Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ - return IntItem(cast<ConstantInt>(NewVal)); \ - } - -#define INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(op) \ - IntItem& operator op (const APInt& RHS) {\ - APInt res = getAPIntValue();\ - res op RHS; \ - Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ - ConstantIntVal = cast<ConstantInt>(NewVal); \ - return *this; \ - } - -#define INT_ITEM_DEFINE_PREINCDEC(op) \ - IntItem& operator op () { \ - APInt res = getAPIntValue(); \ - op(res); \ - Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ - ConstantIntVal = cast<ConstantInt>(NewVal); \ - return *this; \ - } - -#define INT_ITEM_DEFINE_POSTINCDEC(op) \ - IntItem& operator op (int) { \ - APInt res = getAPIntValue();\ - op(res); \ - Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ - OldConstantIntVal = ConstantIntVal; \ - ConstantIntVal = cast<ConstantInt>(NewVal); \ - return IntItem(OldConstantIntVal); \ - } - -#define INT_ITEM_DEFINE_OP_STANDARD_INT(RetTy, op, IntTy) \ - RetTy operator op (IntTy RHS) const { \ - return (*this) op APInt(getAPIntValue().getBitWidth(), RHS); \ - } - -class IntItem { - ConstantInt *ConstantIntVal; - const APInt* APIntVal; - IntItem(const ConstantInt *V) : - ConstantIntVal(const_cast<ConstantInt*>(V)), - APIntVal(&ConstantIntVal->getValue()){} - const APInt& getAPIntValue() const { - return *APIntVal; - } -public: - - IntItem() {} - - operator const APInt&() const { - return getAPIntValue(); - } - - // Propagate APInt operators. - // Note, that - // /,/=,>>,>>= are not implemented in APInt. - // <<= is implemented for unsigned RHS, but not implemented for APInt RHS. - - INT_ITEM_DEFINE_COMPARISON(<, ult) - INT_ITEM_DEFINE_COMPARISON(>, ugt) - INT_ITEM_DEFINE_COMPARISON(<=, ule) - INT_ITEM_DEFINE_COMPARISON(>=, uge) - - INT_ITEM_DEFINE_COMPARISON(==, eq) - INT_ITEM_DEFINE_OP_STANDARD_INT(bool,==,uint64_t) - - INT_ITEM_DEFINE_COMPARISON(!=, ne) - INT_ITEM_DEFINE_OP_STANDARD_INT(bool,!=,uint64_t) - - INT_ITEM_DEFINE_BINARY_OP(*) - INT_ITEM_DEFINE_BINARY_OP(+) - INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,+,uint64_t) - INT_ITEM_DEFINE_BINARY_OP(-) - INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,-,uint64_t) - INT_ITEM_DEFINE_BINARY_OP(<<) - INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,<<,unsigned) - INT_ITEM_DEFINE_BINARY_OP(&) - INT_ITEM_DEFINE_BINARY_OP(^) - INT_ITEM_DEFINE_BINARY_OP(|) - - INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(*=) - INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(+=) - INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(-=) - INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(&=) - INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(^=) - INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(|=) - - // Special case for <<= - IntItem& operator <<= (unsigned RHS) { - APInt res = getAPIntValue(); - res <<= RHS; - Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); - ConstantIntVal = cast<ConstantInt>(NewVal); - return *this; - } - - INT_ITEM_DEFINE_UNARY_OP(-) - INT_ITEM_DEFINE_UNARY_OP(~) - - INT_ITEM_DEFINE_PREINCDEC(++) - INT_ITEM_DEFINE_PREINCDEC(--) - - // The set of workarounds, since currently we use ConstantInt implemented - // integer. - - static IntItem fromConstantInt(const ConstantInt *V) { - return IntItem(V); - } - static IntItem fromType(Type* Ty, const APInt& V) { - ConstantInt *C = cast<ConstantInt>(ConstantInt::get(Ty, V)); - return fromConstantInt(C); - } - static IntItem withImplLikeThis(const IntItem& LikeThis, const APInt& V) { - ConstantInt *C = cast<ConstantInt>(ConstantInt::get( - LikeThis.ConstantIntVal->getContext(), V)); - return fromConstantInt(C); - } - ConstantInt *toConstantInt() const { - return ConstantIntVal; - } -}; - -template<class IntType> -class IntRange { -protected: - IntType Low; - IntType High; - bool IsEmpty : 1; - bool IsSingleNumber : 1; - -public: - typedef IntRange<IntType> self; - typedef std::pair<self, self> SubRes; - - IntRange() : IsEmpty(true) {} - IntRange(const self &RHS) : - Low(RHS.Low), High(RHS.High), - IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {} - IntRange(const IntType &C) : - Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {} - - IntRange(const IntType &L, const IntType &H) : Low(L), High(H), - IsEmpty(false), IsSingleNumber(Low == High) {} - - bool isEmpty() const { return IsEmpty; } - bool isSingleNumber() const { return IsSingleNumber; } - - const IntType& getLow() const { - assert(!IsEmpty && "Range is empty."); - return Low; - } - const IntType& getHigh() const { - assert(!IsEmpty && "Range is empty."); - return High; - } - - bool operator<(const self &RHS) const { - assert(!IsEmpty && "Left range is empty."); - assert(!RHS.IsEmpty && "Right range is empty."); - if (Low == RHS.Low) { - if (High > RHS.High) - return true; - return false; - } - if (Low < RHS.Low) - return true; - return false; - } - - bool operator==(const self &RHS) const { - assert(!IsEmpty && "Left range is empty."); - assert(!RHS.IsEmpty && "Right range is empty."); - return Low == RHS.Low && High == RHS.High; - } - - bool operator!=(const self &RHS) const { - return !operator ==(RHS); - } - - static bool LessBySize(const self &LHS, const self &RHS) { - return (LHS.High - LHS.Low) < (RHS.High - RHS.Low); - } - - bool isInRange(const IntType &IntVal) const { - assert(!IsEmpty && "Range is empty."); - return IntVal >= Low && IntVal <= High; - } - - SubRes sub(const self &RHS) const { - SubRes Res; - - // RHS is either more global and includes this range or - // if it doesn't intersected with this range. - if (!isInRange(RHS.Low) && !isInRange(RHS.High)) { - - // If RHS more global (it is enough to check - // only one border in this case. - if (RHS.isInRange(Low)) - return std::make_pair(self(Low, High), self()); - - return Res; - } - - if (Low < RHS.Low) { - Res.first.Low = Low; - IntType NewHigh = RHS.Low; - --NewHigh; - Res.first.High = NewHigh; - } - if (High > RHS.High) { - IntType NewLow = RHS.High; - ++NewLow; - Res.second.Low = NewLow; - Res.second.High = High; - } - return Res; - } - }; - -//===----------------------------------------------------------------------===// -/// IntegersSubsetGeneric - class that implements the subset of integers. It -/// consists from ranges and single numbers. -template <class IntTy> -class IntegersSubsetGeneric { -public: - // Use Chris Lattner idea, that was initially described here: - // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20120213/136954.html - // In short, for more compact memory consumption we can store flat - // numbers collection, and define range as pair of indices. - // In that case we can safe some memory on 32 bit machines. - typedef std::vector<IntTy> FlatCollectionTy; - typedef std::pair<IntTy*, IntTy*> RangeLinkTy; - typedef std::vector<RangeLinkTy> RangeLinksTy; - typedef typename RangeLinksTy::const_iterator RangeLinksConstIt; - - typedef IntegersSubsetGeneric<IntTy> self; - -protected: - - FlatCollectionTy FlatCollection; - RangeLinksTy RangeLinks; - - bool IsSingleNumber; - bool IsSingleNumbersOnly; - -public: - - template<class RangesCollectionTy> - explicit IntegersSubsetGeneric(const RangesCollectionTy& Links) { - assert(Links.size() && "Empty ranges are not allowed."); - - // In case of big set of single numbers consumes additional RAM space, - // but allows to avoid additional reallocation. - FlatCollection.reserve(Links.size() * 2); - RangeLinks.reserve(Links.size()); - IsSingleNumbersOnly = true; - for (typename RangesCollectionTy::const_iterator i = Links.begin(), - e = Links.end(); i != e; ++i) { - RangeLinkTy RangeLink; - FlatCollection.push_back(i->getLow()); - RangeLink.first = &FlatCollection.back(); - if (i->getLow() != i->getHigh()) { - FlatCollection.push_back(i->getHigh()); - IsSingleNumbersOnly = false; - } - RangeLink.second = &FlatCollection.back(); - RangeLinks.push_back(RangeLink); - } - IsSingleNumber = IsSingleNumbersOnly && RangeLinks.size() == 1; - } - - IntegersSubsetGeneric(const self& RHS) { - *this = RHS; - } - - self& operator=(const self& RHS) { - FlatCollection.clear(); - RangeLinks.clear(); - FlatCollection.reserve(RHS.RangeLinks.size() * 2); - RangeLinks.reserve(RHS.RangeLinks.size()); - for (RangeLinksConstIt i = RHS.RangeLinks.begin(), e = RHS.RangeLinks.end(); - i != e; ++i) { - RangeLinkTy RangeLink; - FlatCollection.push_back(*(i->first)); - RangeLink.first = &FlatCollection.back(); - if (i->first != i->second) - FlatCollection.push_back(*(i->second)); - RangeLink.second = &FlatCollection.back(); - RangeLinks.push_back(RangeLink); - } - IsSingleNumber = RHS.IsSingleNumber; - IsSingleNumbersOnly = RHS.IsSingleNumbersOnly; - return *this; - } - - typedef IntRange<IntTy> Range; - - /// Checks is the given constant satisfies this case. Returns - /// true if it equals to one of contained values or belongs to the one of - /// contained ranges. - bool isSatisfies(const IntTy &CheckingVal) const { - if (IsSingleNumber) - return FlatCollection.front() == CheckingVal; - if (IsSingleNumbersOnly) - return std::find(FlatCollection.begin(), - FlatCollection.end(), - CheckingVal) != FlatCollection.end(); - - for (size_t i = 0, e = getNumItems(); i < e; ++i) { - if (RangeLinks[i].first == RangeLinks[i].second) { - if (*RangeLinks[i].first == CheckingVal) - return true; - } else if (*RangeLinks[i].first <= CheckingVal && - *RangeLinks[i].second >= CheckingVal) - return true; - } - return false; - } - - /// Returns set's item with given index. - Range getItem(unsigned idx) const { - const RangeLinkTy &Link = RangeLinks[idx]; - if (Link.first != Link.second) - return Range(*Link.first, *Link.second); - else - return Range(*Link.first); - } - - /// Return number of items (ranges) stored in set. - size_t getNumItems() const { - return RangeLinks.size(); - } - - /// Returns true if whole subset contains single element. - bool isSingleNumber() const { - return IsSingleNumber; - } - - /// Returns true if whole subset contains only single numbers, no ranges. - bool isSingleNumbersOnly() const { - return IsSingleNumbersOnly; - } - - /// Does the same like getItem(idx).isSingleNumber(), but - /// works faster, since we avoid creation of temporary range object. - bool isSingleNumber(unsigned idx) const { - return RangeLinks[idx].first == RangeLinks[idx].second; - } - - /// Returns set the size, that equals number of all values + sizes of all - /// ranges. - /// Ranges set is considered as flat numbers collection. - /// E.g.: for range [<0>, <1>, <4,8>] the size will 7; - /// for range [<0>, <1>, <5>] the size will 3 - unsigned getSize() const { - APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); - for (size_t i = 0, e = getNumItems(); i != e; ++i) { - const APInt Low = getItem(i).getLow(); - const APInt High = getItem(i).getHigh(); - APInt S = High - Low + 1; - sz += S; - } - return sz.getZExtValue(); - } - - /// Allows to access single value even if it belongs to some range. - /// Ranges set is considered as flat numbers collection. - /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] - /// For range [<1>, <4,8>] getSingleValue(3) returns 6. - APInt getSingleValue(unsigned idx) const { - APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); - for (unsigned i = 0, e = getNumItems(); i != e; ++i) { - const APInt Low = getItem(i).getLow(); - const APInt High = getItem(i).getHigh(); - APInt S = High - Low + 1; - APInt oldSz = sz; - sz += S; - if (sz.ugt(idx)) { - APInt Res = Low; - APInt Offset(oldSz.getBitWidth(), idx); - Offset -= oldSz; - Res += Offset; - return Res; - } - } - assert(0 && "Index exceeds high border."); - return sz; - } - - /// Does the same as getSingleValue, but works only if subset contains - /// single numbers only. - const IntTy& getSingleNumber(unsigned idx) const { - assert(IsSingleNumbersOnly && "This method works properly if subset " - "contains single numbers only."); - return FlatCollection[idx]; - } -}; - -//===----------------------------------------------------------------------===// -/// IntegersSubset - currently is extension of IntegersSubsetGeneric -/// that also supports conversion to/from Constant* object. -class IntegersSubset : public IntegersSubsetGeneric<IntItem> { - - typedef IntegersSubsetGeneric<IntItem> ParentTy; - - Constant *Holder; - - static unsigned getNumItemsFromConstant(Constant *C) { - return cast<ArrayType>(C->getType())->getNumElements(); - } - - static Range getItemFromConstant(Constant *C, unsigned idx) { - const Constant *CV = C->getAggregateElement(idx); - - unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements(); - switch (NumEls) { - case 1: - return Range(IntItem::fromConstantInt( - cast<ConstantInt>(CV->getAggregateElement(0U))), - IntItem::fromConstantInt(cast<ConstantInt>( - cast<ConstantInt>(CV->getAggregateElement(0U))))); - case 2: - return Range(IntItem::fromConstantInt( - cast<ConstantInt>(CV->getAggregateElement(0U))), - IntItem::fromConstantInt( - cast<ConstantInt>(CV->getAggregateElement(1)))); - default: - assert(0 && "Only pairs and single numbers are allowed here."); - return Range(); - } - } - - std::vector<Range> rangesFromConstant(Constant *C) { - unsigned NumItems = getNumItemsFromConstant(C); - std::vector<Range> r; - r.reserve(NumItems); - for (unsigned i = 0, e = NumItems; i != e; ++i) - r.push_back(getItemFromConstant(C, i)); - return r; - } - -public: - - explicit IntegersSubset(Constant *C) : ParentTy(rangesFromConstant(C)), - Holder(C) {} - - IntegersSubset(const IntegersSubset& RHS) : - ParentTy(*(const ParentTy *)&RHS), // FIXME: tweak for msvc. - Holder(RHS.Holder) {} - - template<class RangesCollectionTy> - explicit IntegersSubset(const RangesCollectionTy& Src) : ParentTy(Src) { - std::vector<Constant*> Elts; - Elts.reserve(Src.size()); - for (typename RangesCollectionTy::const_iterator i = Src.begin(), - e = Src.end(); i != e; ++i) { - const Range &R = *i; - std::vector<Constant*> r; - if (R.isSingleNumber()) { - r.reserve(2); - // FIXME: Since currently we have ConstantInt based numbers - // use hack-conversion of IntItem to ConstantInt - r.push_back(R.getLow().toConstantInt()); - r.push_back(R.getHigh().toConstantInt()); - } else { - r.reserve(1); - r.push_back(R.getLow().toConstantInt()); - } - Constant *CV = ConstantVector::get(r); - Elts.push_back(CV); - } - ArrayType *ArrTy = - ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size()); - Holder = ConstantArray::get(ArrTy, Elts); - } - - operator Constant*() { return Holder; } - operator const Constant*() const { return Holder; } - Constant *operator->() { return Holder; } - const Constant *operator->() const { return Holder; } -}; - -} - -#endif /* CLLVM_SUPPORT_INTEGERSSUBSET_H */ diff --git a/include/llvm/Support/IntegersSubsetMapping.h b/include/llvm/Support/IntegersSubsetMapping.h deleted file mode 100644 index 641ce78..0000000 --- a/include/llvm/Support/IntegersSubsetMapping.h +++ /dev/null @@ -1,588 +0,0 @@ -//===- IntegersSubsetMapping.h - Mapping subset ==> Successor ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// @file -/// IntegersSubsetMapping is mapping from A to B, where -/// Items in A is subsets of integers, -/// Items in B some pointers (Successors). -/// If user which to add another subset for successor that is already -/// exists in mapping, IntegersSubsetMapping merges existing subset with -/// added one. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H -#define LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H - -#include "llvm/Support/IntegersSubset.h" -#include <list> -#include <map> -#include <vector> - -namespace llvm { - -template <class SuccessorClass, - class IntegersSubsetTy = IntegersSubset, - class IntTy = IntItem> -class IntegersSubsetMapping { - // FIXME: To much similar iterators typedefs, similar names. - // - Rename RangeIterator to the cluster iterator. - // - Remove unused "add" methods. - // - Class contents needs cleaning. -public: - - typedef IntRange<IntTy> RangeTy; - - struct RangeEx : public RangeTy { - RangeEx() : Weight(1) {} - RangeEx(const RangeTy &R) : RangeTy(R), Weight(1) {} - RangeEx(const RangeTy &R, unsigned W) : RangeTy(R), Weight(W) {} - RangeEx(const IntTy &C) : RangeTy(C), Weight(1) {} - RangeEx(const IntTy &L, const IntTy &H) : RangeTy(L, H), Weight(1) {} - RangeEx(const IntTy &L, const IntTy &H, unsigned W) : - RangeTy(L, H), Weight(W) {} - unsigned Weight; - }; - - typedef std::pair<RangeEx, SuccessorClass*> Cluster; - - typedef std::list<RangeTy> RangesCollection; - typedef typename RangesCollection::iterator RangesCollectionIt; - typedef typename RangesCollection::const_iterator RangesCollectionConstIt; - typedef IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> self; - -protected: - - typedef std::list<Cluster> CaseItems; - typedef typename CaseItems::iterator CaseItemIt; - typedef typename CaseItems::const_iterator CaseItemConstIt; - - // TODO: Change unclean CRS prefixes to SubsetMap for example. - typedef std::map<SuccessorClass*, RangesCollection > CRSMap; - typedef typename CRSMap::iterator CRSMapIt; - - struct ClustersCmp { - bool operator()(const Cluster &C1, const Cluster &C2) { - return C1.first < C2.first; - } - }; - - CaseItems Items; - bool Sorted; - - bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { - return LItem->first.getHigh() >= RItem->first.getLow(); - } - - bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) { - if (LItem->second != RItem->second) { - assert(!isIntersected(LItem, RItem) && - "Intersected items with different successors!"); - return false; - } - APInt RLow = RItem->first.getLow(); - if (RLow != APInt::getNullValue(RLow.getBitWidth())) - --RLow; - return LItem->first.getHigh() >= RLow; - } - - void sort() { - if (!Sorted) { - std::vector<Cluster> clustersVector; - clustersVector.reserve(Items.size()); - clustersVector.insert(clustersVector.begin(), Items.begin(), Items.end()); - std::sort(clustersVector.begin(), clustersVector.end(), ClustersCmp()); - Items.clear(); - Items.insert(Items.begin(), clustersVector.begin(), clustersVector.end()); - Sorted = true; - } - } - - enum DiffProcessState { - L_OPENED, - INTERSECT_OPENED, - R_OPENED, - ALL_IS_CLOSED - }; - - class DiffStateMachine { - - DiffProcessState State; - IntTy OpenPt; - SuccessorClass *CurrentLSuccessor; - SuccessorClass *CurrentRSuccessor; - - self *LeftMapping; - self *IntersectionMapping; - self *RightMapping; - - public: - - typedef - IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> MappingTy; - - DiffStateMachine(MappingTy *L, - MappingTy *Intersection, - MappingTy *R) : - State(ALL_IS_CLOSED), - LeftMapping(L), - IntersectionMapping(Intersection), - RightMapping(R) - {} - - void onLOpen(const IntTy &Pt, SuccessorClass *S) { - switch (State) { - case R_OPENED: - if (Pt > OpenPt/*Don't add empty ranges.*/ && RightMapping) - RightMapping->add(OpenPt, Pt-1, CurrentRSuccessor); - State = INTERSECT_OPENED; - break; - case ALL_IS_CLOSED: - State = L_OPENED; - break; - default: - assert(0 && "Got unexpected point."); - break; - } - CurrentLSuccessor = S; - OpenPt = Pt; - } - - void onLClose(const IntTy &Pt) { - switch (State) { - case L_OPENED: - assert(Pt >= OpenPt && - "Subset is not sorted or contains overlapped ranges"); - if (LeftMapping) - LeftMapping->add(OpenPt, Pt, CurrentLSuccessor); - State = ALL_IS_CLOSED; - break; - case INTERSECT_OPENED: - if (IntersectionMapping) - IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); - OpenPt = Pt + 1; - State = R_OPENED; - break; - default: - assert(0 && "Got unexpected point."); - break; - } - } - - void onROpen(const IntTy &Pt, SuccessorClass *S) { - switch (State) { - case L_OPENED: - if (Pt > OpenPt && LeftMapping) - LeftMapping->add(OpenPt, Pt-1, CurrentLSuccessor); - State = INTERSECT_OPENED; - break; - case ALL_IS_CLOSED: - State = R_OPENED; - break; - default: - assert(0 && "Got unexpected point."); - break; - } - CurrentRSuccessor = S; - OpenPt = Pt; - } - - void onRClose(const IntTy &Pt) { - switch (State) { - case R_OPENED: - assert(Pt >= OpenPt && - "Subset is not sorted or contains overlapped ranges"); - if (RightMapping) - RightMapping->add(OpenPt, Pt, CurrentRSuccessor); - State = ALL_IS_CLOSED; - break; - case INTERSECT_OPENED: - if (IntersectionMapping) - IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); - OpenPt = Pt + 1; - State = L_OPENED; - break; - default: - assert(0 && "Got unexpected point."); - break; - } - } - - void onLROpen(const IntTy &Pt, - SuccessorClass *LS, - SuccessorClass *RS) { - switch (State) { - case ALL_IS_CLOSED: - State = INTERSECT_OPENED; - break; - default: - assert(0 && "Got unexpected point."); - break; - } - CurrentLSuccessor = LS; - CurrentRSuccessor = RS; - OpenPt = Pt; - } - - void onLRClose(const IntTy &Pt) { - switch (State) { - case INTERSECT_OPENED: - if (IntersectionMapping) - IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); - State = ALL_IS_CLOSED; - break; - default: - assert(0 && "Got unexpected point."); - break; - } - } - - bool isLOpened() { return State == L_OPENED; } - bool isROpened() { return State == R_OPENED; } - }; - -public: - - // Don't public CaseItems itself. Don't allow edit the Items directly. - // Just present the user way to iterate over the internal collection - // sharing iterator, begin() and end(). Editing should be controlled by - // factory. - typedef CaseItemIt RangeIterator; - - typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case; - typedef std::list<Case> Cases; - typedef typename Cases::iterator CasesIt; - - IntegersSubsetMapping() { - Sorted = false; - } - - bool verify() { - RangeIterator DummyErrItem; - return verify(DummyErrItem); - } - - bool verify(RangeIterator& errItem) { - if (Items.empty()) - return true; - sort(); - for (CaseItemIt j = Items.begin(), i = j++, e = Items.end(); - j != e; i = j++) { - if (isIntersected(i, j) && i->second != j->second) { - errItem = j; - return false; - } - } - return true; - } - - bool isOverlapped(self &RHS) { - if (Items.empty() || RHS.empty()) - return true; - - for (CaseItemIt L = Items.begin(), R = RHS.Items.begin(), - el = Items.end(), er = RHS.Items.end(); L != el && R != er;) { - - const RangeTy &LRange = L->first; - const RangeTy &RRange = R->first; - - if (LRange.getLow() > RRange.getLow()) { - if (RRange.isSingleNumber() || LRange.getLow() > RRange.getHigh()) - ++R; - else - return true; - } else if (LRange.getLow() < RRange.getLow()) { - if (LRange.isSingleNumber() || LRange.getHigh() < RRange.getLow()) - ++L; - else - return true; - } else // iRange.getLow() == jRange.getLow() - return true; - } - return false; - } - - - void optimize() { - if (Items.size() < 2) - return; - sort(); - CaseItems OldItems = Items; - Items.clear(); - const IntTy *Low = &OldItems.begin()->first.getLow(); - const IntTy *High = &OldItems.begin()->first.getHigh(); - unsigned Weight = OldItems.begin()->first.Weight; - SuccessorClass *Successor = OldItems.begin()->second; - for (CaseItemIt j = OldItems.begin(), i = j++, e = OldItems.end(); - j != e; i = j++) { - if (isJoinable(i, j)) { - const IntTy *CurHigh = &j->first.getHigh(); - Weight += j->first.Weight; - if (*CurHigh > *High) - High = CurHigh; - } else { - RangeEx R(*Low, *High, Weight); - add(R, Successor); - Low = &j->first.getLow(); - High = &j->first.getHigh(); - Weight = j->first.Weight; - Successor = j->second; - } - } - RangeEx R(*Low, *High, Weight); - add(R, Successor); - // We recollected the Items, but we kept it sorted. - Sorted = true; - } - - /// Adds a constant value. - void add(const IntTy &C, SuccessorClass *S = 0) { - RangeTy R(C); - add(R, S); - } - - /// Adds a range. - void add(const IntTy &Low, const IntTy &High, SuccessorClass *S = 0) { - RangeTy R(Low, High); - add(R, S); - } - void add(const RangeTy &R, SuccessorClass *S = 0) { - RangeEx REx = R; - add(REx, S); - } - void add(const RangeEx &R, SuccessorClass *S = 0) { - Items.push_back(std::make_pair(R, S)); - Sorted = false; - } - - /// Adds all ranges and values from given ranges set to the current - /// mapping. - void add(const IntegersSubsetTy &CRS, SuccessorClass *S = 0, - unsigned Weight = 0) { - unsigned ItemWeight = 1; - if (Weight) - // Weight is associated with CRS, for now we perform a division to - // get the weight for each item. - ItemWeight = Weight / CRS.getNumItems(); - for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) { - RangeTy R = CRS.getItem(i); - RangeEx REx(R, ItemWeight); - add(REx, S); - } - } - - void add(self& RHS) { - Items.insert(Items.end(), RHS.Items.begin(), RHS.Items.end()); - } - - void add(self& RHS, SuccessorClass *S) { - for (CaseItemIt i = RHS.Items.begin(), e = RHS.Items.end(); i != e; ++i) - add(i->first, S); - } - - void add(const RangesCollection& RHS, SuccessorClass *S = 0) { - for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i) - add(*i, S); - } - - /// Removes items from set. - void removeItem(RangeIterator i) { Items.erase(i); } - - /// Moves whole case from current mapping to the NewMapping object. - void detachCase(self& NewMapping, SuccessorClass *Succ) { - for (CaseItemIt i = Items.begin(); i != Items.end();) - if (i->second == Succ) { - NewMapping.add(i->first, i->second); - Items.erase(i++); - } else - ++i; - } - - /// Removes all clusters for given successor. - void removeCase(SuccessorClass *Succ) { - for (CaseItemIt i = Items.begin(); i != Items.end();) - if (i->second == Succ) { - Items.erase(i++); - } else - ++i; - } - - /// Find successor that satisfies given value. - SuccessorClass *findSuccessor(const IntTy& Val) { - for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) { - if (i->first.isInRange(Val)) - return i->second; - } - return 0; - } - - /// Calculates the difference between this mapping and RHS. - /// THIS without RHS is placed into LExclude, - /// RHS without THIS is placed into RExclude, - /// THIS intersect RHS is placed into Intersection. - void diff(self *LExclude, self *Intersection, self *RExclude, - const self& RHS) { - - DiffStateMachine Machine(LExclude, Intersection, RExclude); - - CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); - while (L != Items.end() && R != RHS.Items.end()) { - const Cluster &LCluster = *L; - const RangeEx &LRange = LCluster.first; - const Cluster &RCluster = *R; - const RangeEx &RRange = RCluster.first; - - if (LRange.getHigh() < RRange.getLow()) { - Machine.onLOpen(LRange.getLow(), LCluster.second); - Machine.onLClose(LRange.getHigh()); - ++L; - continue; - } - - if (LRange.getLow() > RRange.getHigh()) { - Machine.onROpen(RRange.getLow(), RCluster.second); - Machine.onRClose(RRange.getHigh()); - ++R; - continue; - } - - if (LRange.getLow() < RRange.getLow()) { - // May be opened in previous iteration. - if (!Machine.isLOpened()) - Machine.onLOpen(LRange.getLow(), LCluster.second); - Machine.onROpen(RRange.getLow(), RCluster.second); - } - else if (RRange.getLow() < LRange.getLow()) { - if (!Machine.isROpened()) - Machine.onROpen(RRange.getLow(), RCluster.second); - Machine.onLOpen(LRange.getLow(), LCluster.second); - } - else - Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); - - if (LRange.getHigh() < RRange.getHigh()) { - Machine.onLClose(LRange.getHigh()); - ++L; - while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) { - Machine.onLOpen(L->first.getLow(), L->second); - Machine.onLClose(L->first.getHigh()); - ++L; - } - } - else if (RRange.getHigh() < LRange.getHigh()) { - Machine.onRClose(RRange.getHigh()); - ++R; - while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) { - Machine.onROpen(R->first.getLow(), R->second); - Machine.onRClose(R->first.getHigh()); - ++R; - } - } - else { - Machine.onLRClose(LRange.getHigh()); - ++L; - ++R; - } - } - - if (L != Items.end()) { - if (Machine.isLOpened()) { - Machine.onLClose(L->first.getHigh()); - ++L; - } - if (LExclude) - while (L != Items.end()) { - LExclude->add(L->first, L->second); - ++L; - } - } else if (R != RHS.Items.end()) { - if (Machine.isROpened()) { - Machine.onRClose(R->first.getHigh()); - ++R; - } - if (RExclude) - while (R != RHS.Items.end()) { - RExclude->add(R->first, R->second); - ++R; - } - } - } - - /// Builds the finalized case objects. - void getCases(Cases& TheCases, bool PreventMerging = false) { - //FIXME: PreventMerging is a temporary parameter. - //Currently a set of passes is still knows nothing about - //switches with case ranges, and if these passes meet switch - //with complex case that crashs the application. - if (PreventMerging) { - for (RangeIterator i = this->begin(); i != this->end(); ++i) { - RangesCollection SingleRange; - SingleRange.push_back(i->first); - TheCases.push_back(std::make_pair(i->second, - IntegersSubsetTy(SingleRange))); - } - return; - } - CRSMap TheCRSMap; - for (RangeIterator i = this->begin(); i != this->end(); ++i) - TheCRSMap[i->second].push_back(i->first); - for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i) - TheCases.push_back(std::make_pair(i->first, IntegersSubsetTy(i->second))); - } - - /// Builds the finalized case objects ignoring successor values, as though - /// all ranges belongs to the same successor. - IntegersSubsetTy getCase() { - RangesCollection Ranges; - for (RangeIterator i = this->begin(); i != this->end(); ++i) - Ranges.push_back(i->first); - return IntegersSubsetTy(Ranges); - } - - /// Returns pointer to value of case if it is single-numbered or 0 - /// in another case. - const IntTy* getCaseSingleNumber(SuccessorClass *Succ) { - const IntTy* Res = 0; - for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) - if (i->second == Succ) { - if (!i->first.isSingleNumber()) - return 0; - if (Res) - return 0; - else - Res = &(i->first.getLow()); - } - return Res; - } - - /// Returns true if there is no ranges and values inside. - bool empty() const { return Items.empty(); } - - void clear() { - Items.clear(); - // Don't reset Sorted flag: - // 1. For empty mapping it matters nothing. - // 2. After first item will added Sorted flag will cleared. - } - - // Returns number of clusters - unsigned size() const { - return Items.size(); - } - - RangeIterator begin() { return Items.begin(); } - RangeIterator end() { return Items.end(); } -}; - -class BasicBlock; -typedef IntegersSubsetMapping<BasicBlock> IntegersSubsetToBB; - -} - -#endif /* LLVM_SUPPORT_INTEGERSSUBSETMAPPING_CRSBUILDER_H */ diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 7f28c3f..897a611 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -14,273 +14,419 @@ #ifndef LLVM_SUPPORT_MACHO_H #define LLVM_SUPPORT_MACHO_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Host.h" -// NOTE: The enums in this file are intentially named to be different than those -// in the headers in /usr/include/mach (on darwin systems) to avoid conflicts -// with those macros. namespace llvm { namespace MachO { // Enums from <mach-o/loader.h> - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // Constants for the "magic" field in llvm::MachO::mach_header and // llvm::MachO::mach_header_64 - HeaderMagic32 = 0xFEEDFACEu, // MH_MAGIC - HeaderMagic32Swapped = 0xCEFAEDFEu, // MH_CIGAM - HeaderMagic64 = 0xFEEDFACFu, // MH_MAGIC_64 - HeaderMagic64Swapped = 0xCFFAEDFEu, // MH_CIGAM_64 - UniversalMagic = 0xCAFEBABEu, // FAT_MAGIC - UniversalMagicSwapped = 0xBEBAFECAu, // FAT_CIGAM + MH_MAGIC = 0xFEEDFACEu, + MH_CIGAM = 0xCEFAEDFEu, + MH_MAGIC_64 = 0xFEEDFACFu, + MH_CIGAM_64 = 0xCFFAEDFEu, + FAT_MAGIC = 0xCAFEBABEu, + FAT_CIGAM = 0xBEBAFECAu + }; + enum HeaderFileType { // Constants for the "filetype" field in llvm::MachO::mach_header and // llvm::MachO::mach_header_64 - HeaderFileTypeObject = 0x1u, // MH_OBJECT - HeaderFileTypeExecutable = 0x2u, // MH_EXECUTE - HeaderFileTypeFixedVMShlib = 0x3u, // MH_FVMLIB - HeaderFileTypeCore = 0x4u, // MH_CORE - HeaderFileTypePreloadedExecutable = 0x5u, // MH_PRELOAD - HeaderFileTypeDynamicShlib = 0x6u, // MH_DYLIB - HeaderFileTypeDynamicLinkEditor = 0x7u, // MH_DYLINKER - HeaderFileTypeBundle = 0x8u, // MH_BUNDLE - HeaderFileTypeDynamicShlibStub = 0x9u, // MH_DYLIB_STUB - HeaderFileTypeDSYM = 0xAu, // MH_DSYM - HeaderFileTypeKextBundle = 0xBu, // MH_KEXT_BUNDLE + MH_OBJECT = 0x1u, + MH_EXECUTE = 0x2u, + MH_FVMLIB = 0x3u, + MH_CORE = 0x4u, + MH_PRELOAD = 0x5u, + MH_DYLIB = 0x6u, + MH_DYLINKER = 0x7u, + MH_BUNDLE = 0x8u, + MH_DYLIB_STUB = 0x9u, + MH_DSYM = 0xAu, + MH_KEXT_BUNDLE = 0xBu + }; + enum { // Constant bits for the "flags" field in llvm::MachO::mach_header and // llvm::MachO::mach_header_64 - HeaderFlagBitNoUndefinedSymbols = 0x00000001u, // MH_NOUNDEFS - HeaderFlagBitIsIncrementalLinkObject= 0x00000002u, // MH_INCRLINK - HeaderFlagBitIsDynamicLinkObject = 0x00000004u, // MH_DYLDLINK - HeaderFlagBitBindAtLoad = 0x00000008u, // MH_BINDATLOAD - HeaderFlagBitPrebound = 0x00000010u, // MH_PREBOUND - HeaderFlagBitSplitSegments = 0x00000020u, // MH_SPLIT_SEGS - HeaderFlagBitLazyInit = 0x00000040u, // MH_LAZY_INIT - HeaderFlagBitTwoLevelNamespace = 0x00000080u, // MH_TWOLEVEL - HeaderFlagBitForceFlatNamespace = 0x00000100u, // MH_FORCE_FLAT - HeaderFlagBitNoMultipleDefintions = 0x00000200u, // MH_NOMULTIDEFS - HeaderFlagBitNoFixPrebinding = 0x00000400u, // MH_NOFIXPREBINDING - HeaderFlagBitPrebindable = 0x00000800u, // MH_PREBINDABLE - HeaderFlagBitAllModulesBound = 0x00001000u, // MH_ALLMODSBOUND - HeaderFlagBitSubsectionsViaSymbols = 0x00002000u, // MH_SUBSECTIONS_VIA_SYMBOLS - HeaderFlagBitCanonical = 0x00004000u, // MH_CANONICAL - HeaderFlagBitWeakDefines = 0x00008000u, // MH_WEAK_DEFINES - HeaderFlagBitBindsToWeak = 0x00010000u, // MH_BINDS_TO_WEAK - HeaderFlagBitAllowStackExecution = 0x00020000u, // MH_ALLOW_STACK_EXECUTION - HeaderFlagBitRootSafe = 0x00040000u, // MH_ROOT_SAFE - HeaderFlagBitSetUIDSafe = 0x00080000u, // MH_SETUID_SAFE - HeaderFlagBitNoReexportedDylibs = 0x00100000u, // MH_NO_REEXPORTED_DYLIBS - HeaderFlagBitPIE = 0x00200000u, // MH_PIE - HeaderFlagBitDeadStrippableDylib = 0x00400000u, // MH_DEAD_STRIPPABLE_DYLIB - + MH_NOUNDEFS = 0x00000001u, + MH_INCRLINK = 0x00000002u, + MH_DYLDLINK = 0x00000004u, + MH_BINDATLOAD = 0x00000008u, + MH_PREBOUND = 0x00000010u, + MH_SPLIT_SEGS = 0x00000020u, + MH_LAZY_INIT = 0x00000040u, + MH_TWOLEVEL = 0x00000080u, + MH_FORCE_FLAT = 0x00000100u, + MH_NOMULTIDEFS = 0x00000200u, + MH_NOFIXPREBINDING = 0x00000400u, + MH_PREBINDABLE = 0x00000800u, + MH_ALLMODSBOUND = 0x00001000u, + MH_SUBSECTIONS_VIA_SYMBOLS = 0x00002000u, + MH_CANONICAL = 0x00004000u, + MH_WEAK_DEFINES = 0x00008000u, + MH_BINDS_TO_WEAK = 0x00010000u, + MH_ALLOW_STACK_EXECUTION = 0x00020000u, + MH_ROOT_SAFE = 0x00040000u, + MH_SETUID_SAFE = 0x00080000u, + MH_NO_REEXPORTED_DYLIBS = 0x00100000u, + MH_PIE = 0x00200000u, + MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u + }; + + enum LLVM_ENUM_INT_TYPE(uint32_t) { + // Flags for the "cmd" field in llvm::MachO::load_command + LC_REQ_DYLD = 0x80000000u + }; + + enum LoadCommandType LLVM_ENUM_INT_TYPE(uint32_t) { // Constants for the "cmd" field in llvm::MachO::load_command - LoadCommandDynamicLinkerRequired = 0x80000000u, // LC_REQ_DYLD - LoadCommandSegment32 = 0x00000001u, // LC_SEGMENT - LoadCommandSymtab = 0x00000002u, // LC_SYMTAB - LoadCommandSymSeg = 0x00000003u, // LC_SYMSEG - LoadCommandThread = 0x00000004u, // LC_THREAD - LoadCommandUnixThread = 0x00000005u, // LC_UNIXTHREAD - LoadCommandFixedVMShlibLoad = 0x00000006u, // LC_LOADFVMLIB - LoadCommandFixedVMShlibIdent = 0x00000007u, // LC_IDFVMLIB - LoadCommandIdent = 0x00000008u, // LC_IDENT - LoadCommandFixedVMFileInclusion = 0x00000009u, // LC_FVMFILE - LoadCommandPrePage = 0x0000000Au, // LC_PREPAGE - LoadCommandDynamicSymtabInfo = 0x0000000Bu, // LC_DYSYMTAB - LoadCommandDylibLoad = 0x0000000Cu, // LC_LOAD_DYLIB - LoadCommandDylibIdent = 0x0000000Du, // LC_ID_DYLIB - LoadCommandDynamicLinkerLoad = 0x0000000Eu, // LC_LOAD_DYLINKER - LoadCommandDynamicLinkerIdent = 0x0000000Fu, // LC_ID_DYLINKER - LoadCommandDylibPrebound = 0x00000010u, // LC_PREBOUND_DYLIB - LoadCommandRoutines32 = 0x00000011u, // LC_ROUTINES - LoadCommandSubFramework = 0x00000012u, // LC_SUB_FRAMEWORK - LoadCommandSubUmbrella = 0x00000013u, // LC_SUB_UMBRELLA - LoadCommandSubClient = 0x00000014u, // LC_SUB_CLIENT - LoadCommandSubLibrary = 0x00000015u, // LC_SUB_LIBRARY - LoadCommandTwoLevelHints = 0x00000016u, // LC_TWOLEVEL_HINTS - LoadCommandPreBindChecksum = 0x00000017u, // LC_PREBIND_CKSUM - LoadCommandDylibLoadWeak = 0x80000018u, // LC_LOAD_WEAK_DYLIB - LoadCommandSegment64 = 0x00000019u, // LC_SEGMENT_64 - LoadCommandRoutines64 = 0x0000001Au, // LC_ROUTINES_64 - LoadCommandUUID = 0x0000001Bu, // LC_UUID - LoadCommandRunpath = 0x8000001Cu, // LC_RPATH - LoadCommandCodeSignature = 0x0000001Du, // LC_CODE_SIGNATURE - LoadCommandSegmentSplitInfo = 0x0000001Eu, // LC_SEGMENT_SPLIT_INFO - LoadCommandDylibReexport = 0x8000001Fu, // LC_REEXPORT_DYLIB - LoadCommandDylibLazyLoad = 0x00000020u, // LC_LAZY_LOAD_DYLIB - LoadCommandEncryptionInfo = 0x00000021u, // LC_ENCRYPTION_INFO - LoadCommandDynamicLinkerInfo = 0x00000022u, // LC_DYLD_INFO - LoadCommandDynamicLinkerInfoOnly = 0x80000022u, // LC_DYLD_INFO_ONLY - LoadCommandDylibLoadUpward = 0x80000023u, // LC_LOAD_UPWARD_DYLIB - LoadCommandVersionMinMacOSX = 0x00000024u, // LC_VERSION_MIN_MACOSX - LoadCommandVersionMinIPhoneOS = 0x00000025u, // LC_VERSION_MIN_IPHONEOS - LoadCommandFunctionStarts = 0x00000026u, // LC_FUNCTION_STARTS - LoadCommandDyldEnvironment = 0x00000027u, // LC_DYLD_ENVIRONMENT - LoadCommandMain = 0x80000028u, // LC_MAIN - LoadCommandDataInCode = 0x00000029u, // LC_DATA_IN_CODE - LoadCommandSourceVersion = 0x0000002Au, // LC_SOURCE_VERSION - LoadCommandCodeSignDRs = 0x0000002Bu, // LC_DYLIB_CODE_SIGN_DRS - + LC_SEGMENT = 0x00000001u, + LC_SYMTAB = 0x00000002u, + LC_SYMSEG = 0x00000003u, + LC_THREAD = 0x00000004u, + LC_UNIXTHREAD = 0x00000005u, + LC_LOADFVMLIB = 0x00000006u, + LC_IDFVMLIB = 0x00000007u, + LC_IDENT = 0x00000008u, + LC_FVMFILE = 0x00000009u, + LC_PREPAGE = 0x0000000Au, + LC_DYSYMTAB = 0x0000000Bu, + LC_LOAD_DYLIB = 0x0000000Cu, + LC_ID_DYLIB = 0x0000000Du, + LC_LOAD_DYLINKER = 0x0000000Eu, + LC_ID_DYLINKER = 0x0000000Fu, + LC_PREBOUND_DYLIB = 0x00000010u, + LC_ROUTINES = 0x00000011u, + LC_SUB_FRAMEWORK = 0x00000012u, + LC_SUB_UMBRELLA = 0x00000013u, + LC_SUB_CLIENT = 0x00000014u, + LC_SUB_LIBRARY = 0x00000015u, + LC_TWOLEVEL_HINTS = 0x00000016u, + LC_PREBIND_CKSUM = 0x00000017u, + LC_LOAD_WEAK_DYLIB = 0x80000018u, + LC_SEGMENT_64 = 0x00000019u, + LC_ROUTINES_64 = 0x0000001Au, + LC_UUID = 0x0000001Bu, + LC_RPATH = 0x8000001Cu, + LC_CODE_SIGNATURE = 0x0000001Du, + LC_SEGMENT_SPLIT_INFO = 0x0000001Eu, + LC_REEXPORT_DYLIB = 0x8000001Fu, + LC_LAZY_LOAD_DYLIB = 0x00000020u, + LC_ENCRYPTION_INFO = 0x00000021u, + LC_DYLD_INFO = 0x00000022u, + LC_DYLD_INFO_ONLY = 0x80000022u, + LC_LOAD_UPWARD_DYLIB = 0x80000023u, + LC_VERSION_MIN_MACOSX = 0x00000024u, + LC_VERSION_MIN_IPHONEOS = 0x00000025u, + LC_FUNCTION_STARTS = 0x00000026u, + LC_DYLD_ENVIRONMENT = 0x00000027u, + LC_MAIN = 0x80000028u, + LC_DATA_IN_CODE = 0x00000029u, + LC_SOURCE_VERSION = 0x0000002Au, + LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu, + // 0x0000002Cu, + LC_LINKER_OPTIONS = 0x0000002Du + }; + + enum LLVM_ENUM_INT_TYPE(uint32_t) { // Constant bits for the "flags" field in llvm::MachO::segment_command - SegmentCommandFlagBitHighVM = 0x1u, // SG_HIGHVM - SegmentCommandFlagBitFixedVMLibrary = 0x2u, // SG_FVMLIB - SegmentCommandFlagBitNoRelocations = 0x4u, // SG_NORELOC - SegmentCommandFlagBitProtectedVersion1 = 0x8u, // SG_PROTECTED_VERSION_1 + SG_HIGHVM = 0x1u, + SG_FVMLIB = 0x2u, + SG_NORELOC = 0x4u, + SG_PROTECTED_VERSION_1 = 0x8u, // Constant masks for the "flags" field in llvm::MachO::section and // llvm::MachO::section_64 - SectionFlagMaskSectionType = 0x000000ffu, // SECTION_TYPE - SectionFlagMaskAllAttributes = 0xffffff00u, // SECTION_ATTRIBUTES - SectionFlagMaskUserAttributes = 0xff000000u, // SECTION_ATTRIBUTES_USR - SectionFlagMaskSystemAttributes = 0x00ffff00u, // SECTION_ATTRIBUTES_SYS + SECTION_TYPE = 0x000000ffu, // SECTION_TYPE + SECTION_ATTRIBUTES = 0xffffff00u, // SECTION_ATTRIBUTES + SECTION_ATTRIBUTES_USR = 0xff000000u, // SECTION_ATTRIBUTES_USR + SECTION_ATTRIBUTES_SYS = 0x00ffff00u // SECTION_ATTRIBUTES_SYS + }; + enum SectionType { // Constant masks for the "flags[7:0]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_TYPE) - SectionTypeRegular = 0x00u, // S_REGULAR - SectionTypeZeroFill = 0x01u, // S_ZEROFILL - SectionTypeCStringLiterals = 0x02u, // S_CSTRING_LITERALS - SectionType4ByteLiterals = 0x03u, // S_4BYTE_LITERALS - SectionType8ByteLiterals = 0x04u, // S_8BYTE_LITERALS - SectionTypeLiteralPointers = 0x05u, // S_LITERAL_POINTERS - SectionTypeNonLazySymbolPointers = 0x06u, // S_NON_LAZY_SYMBOL_POINTERS - SectionTypeLazySymbolPointers = 0x07u, // S_LAZY_SYMBOL_POINTERS - SectionTypeSymbolStubs = 0x08u, // S_SYMBOL_STUBS - SectionTypeModuleInitFunctionPointers = 0x09u, // S_MOD_INIT_FUNC_POINTERS - SectionTypeModuleTermFunctionPointers = 0x0au, // S_MOD_TERM_FUNC_POINTERS - SectionTypeCoalesced = 0x0bu, // S_COALESCED - SectionTypeZeroFillLarge = 0x0cu, // S_GB_ZEROFILL - SectionTypeInterposing = 0x0du, // S_INTERPOSING - SectionType16ByteLiterals = 0x0eu, // S_16BYTE_LITERALS - SectionTypeDTraceObjectFormat = 0x0fu, // S_DTRACE_DOF - SectionTypeLazyDylibSymbolPointers = 0x10u, // S_LAZY_DYLIB_SYMBOL_POINTERS - + S_REGULAR = 0x00u, + S_ZEROFILL = 0x01u, + S_CSTRING_LITERALS = 0x02u, + S_4BYTE_LITERALS = 0x03u, + S_8BYTE_LITERALS = 0x04u, + S_LITERAL_POINTERS = 0x05u, + S_NON_LAZY_SYMBOL_POINTERS = 0x06u, + S_LAZY_SYMBOL_POINTERS = 0x07u, + S_SYMBOL_STUBS = 0x08u, + S_MOD_INIT_FUNC_POINTERS = 0x09u, + S_MOD_TERM_FUNC_POINTERS = 0x0au, + S_COALESCED = 0x0bu, + S_GB_ZEROFILL = 0x0cu, + S_INTERPOSING = 0x0du, + S_16BYTE_LITERALS = 0x0eu, + S_DTRACE_DOF = 0x0fu, + S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10u, + S_THREAD_LOCAL_REGULAR = 0x11u, + S_THREAD_LOCAL_ZEROFILL = 0x12u, + S_THREAD_LOCAL_VARIABLES = 0x13u, + S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14u, + S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u + }; + + enum LLVM_ENUM_INT_TYPE(uint32_t) { // Constant masks for the "flags[31:24]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_USR) - SectionAttrUserPureInstructions = 0x80000000u, // S_ATTR_PURE_INSTRUCTIONS - SectionAttrUserNoTableOfContents = 0x40000000u, // S_ATTR_NO_TOC - SectionAttrUserCanStripStaticSymbols = 0x20000000u, // S_ATTR_STRIP_STATIC_SYMS - SectionAttrUserNoDeadStrip = 0x10000000u, // S_ATTR_NO_DEAD_STRIP - SectionAttrUserLiveSupport = 0x08000000u, // S_ATTR_LIVE_SUPPORT - SectionAttrUserSelfModifyingCode = 0x04000000u, // S_ATTR_SELF_MODIFYING_CODE - SectionAttrUserDebug = 0x02000000u, // S_ATTR_DEBUG + S_ATTR_PURE_INSTRUCTIONS = 0x80000000u, + S_ATTR_NO_TOC = 0x40000000u, + S_ATTR_STRIP_STATIC_SYMS = 0x20000000u, + S_ATTR_NO_DEAD_STRIP = 0x10000000u, + S_ATTR_LIVE_SUPPORT = 0x08000000u, + S_ATTR_SELF_MODIFYING_CODE = 0x04000000u, + S_ATTR_DEBUG = 0x02000000u, // Constant masks for the "flags[23:8]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_SYS) - SectionAttrSytemSomeInstructions = 0x00000400u, // S_ATTR_SOME_INSTRUCTIONS - SectionAttrSytemHasExternalRelocations= 0x00000200u, // S_ATTR_EXT_RELOC - SectionAttrSytemHasLocalRelocations = 0x00000100u, // S_ATTR_LOC_RELOC - - IndirectSymbolLocal = 0x80000000u, // INDIRECT_SYMBOL_LOCAL - IndirectSymbolAbsolute = 0x40000000u, // INDIRECT_SYMBOL_ABS - - RebaseTypePointer = 1u, // REBASE_TYPE_POINTER - RebaseTypeTextAbsolute32 = 2u, // REBASE_TYPE_TEXT_ABSOLUTE32 - RebaseTypeTextPCRelative32 = 3u, // REBASE_TYPE_TEXT_PCREL32 - - RebaseOpcodeMask = 0xF0u, // REBASE_OPCODE_MASK - RebaseImmediateMask = 0x0Fu, // REBASE_IMMEDIATE_MASK - RebaseOpcodeDone = 0x00u, // REBASE_OPCODE_DONE - RebaseOpcodeSetTypeImmediate = 0x10u, // REBASE_OPCODE_SET_TYPE_IMM - RebaseOpcodeSetSegmentAndOffsetULEB = 0x20u, // REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB - RebaseOpcodeAddAddressULEB = 0x30u, // REBASE_OPCODE_ADD_ADDR_ULEB - RebaseOpcodeAddAddressImmediateScaled = 0x40u, // REBASE_OPCODE_ADD_ADDR_IMM_SCALED - RebaseOpcodeDoRebaseImmediateTimes = 0x50u, // REBASE_OPCODE_DO_REBASE_IMM_TIMES - RebaseOpcodeDoRebaseULEBTimes = 0x60u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES - RebaseOpcodeDoRebaseAddAddressULEB = 0x70u, // REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB - RebaseOpcodeDoRebaseULEBTimesSkippingULEB = 0x80u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB - - - BindTypePointer = 1u, // BIND_TYPE_POINTER - BindTypeTextAbsolute32 = 2u, // BIND_TYPE_TEXT_ABSOLUTE32 - BindTypeTextPCRelative32 = 3u, // BIND_TYPE_TEXT_PCREL32 - - BindSpecialDylibSelf = 0u, // BIND_SPECIAL_DYLIB_SELF - BindSpecialDylibMainExecutable = -1u, // BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE - BindSpecialDylibFlatLookup = -2u, // BIND_SPECIAL_DYLIB_FLAT_LOOKUP - - BindSymbolFlagsWeakImport = 0x1u, // BIND_SYMBOL_FLAGS_WEAK_IMPORT - BindSymbolFlagsNonWeakDefinition = 0x8u, // BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION - - BindOpcodeMask = 0xF0u, // BIND_OPCODE_MASK - BindImmediateMask = 0x0Fu, // BIND_IMMEDIATE_MASK - BindOpcodeDone = 0x00u, // BIND_OPCODE_DONE - BindOpcodeSetDylibOrdinalImmediate = 0x10u, // BIND_OPCODE_SET_DYLIB_ORDINAL_IMM - BindOpcodeSetDylibOrdinalULEB = 0x20u, // BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB - BindOpcodeSetDylibSpecialImmediate = 0x30u, // BIND_OPCODE_SET_DYLIB_SPECIAL_IMM - BindOpcodeSetSymbolTrailingFlagsImmediate = 0x40u, // BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM - BindOpcodeSetTypeImmediate = 0x50u, // BIND_OPCODE_SET_TYPE_IMM - BindOpcodeSetAppendSLEB = 0x60u, // BIND_OPCODE_SET_ADDEND_SLEB - BindOpcodeSetSegmentAndOffsetULEB = 0x70u, // BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB - BindOpcodeAddAddressULEB = 0x80u, // BIND_OPCODE_ADD_ADDR_ULEB - BindOpcodeDoBind = 0x90u, // BIND_OPCODE_DO_BIND - BindOpcodeDoBindAddAddressULEB = 0xA0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB - BindOpcodeDoBindAddAddressImmediateScaled = 0xB0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED - BindOpcodeDoBindULEBTimesSkippingULEB = 0xC0u, // BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB - - ExportSymbolFlagsKindMask = 0x03u, // EXPORT_SYMBOL_FLAGS_KIND_MASK - ExportSymbolFlagsKindRegular = 0x00u, // EXPORT_SYMBOL_FLAGS_KIND_REGULAR - ExportSymbolFlagsKindThreadLocal = 0x01u, // EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL - ExportSymbolFlagsWeakDefinition = 0x04u, // EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION - ExportSymbolFlagsIndirectDefinition = 0x08u, // EXPORT_SYMBOL_FLAGS_INDIRECT_DEFINITION - ExportSymbolFlagsHasSpecializations = 0x10u, // EXPORT_SYMBOL_FLAGS_HAS_SPECIALIZATIONS + S_ATTR_SOME_INSTRUCTIONS = 0x00000400u, + S_ATTR_EXT_RELOC = 0x00000200u, + S_ATTR_LOC_RELOC = 0x00000100u, + + // Constant masks for the value of an indirect symbol in an indirect + // symbol table + INDIRECT_SYMBOL_LOCAL = 0x80000000u, + INDIRECT_SYMBOL_ABS = 0x40000000u + }; + + enum DataRegionType { + // Constants for the "kind" field in a data_in_code_entry structure + DICE_KIND_DATA = 1u, + DICE_KIND_JUMP_TABLE8 = 2u, + DICE_KIND_JUMP_TABLE16 = 3u, + DICE_KIND_JUMP_TABLE32 = 4u, + DICE_KIND_ABS_JUMP_TABLE32 = 5u + }; + + enum RebaseType { + REBASE_TYPE_POINTER = 1u, + REBASE_TYPE_TEXT_ABSOLUTE32 = 2u, + REBASE_TYPE_TEXT_PCREL32 = 3u + }; + + enum { + REBASE_OPCODE_MASK = 0xF0u, + REBASE_IMMEDIATE_MASK = 0x0Fu + }; + + enum RebaseOpcode { + REBASE_OPCODE_DONE = 0x00u, + REBASE_OPCODE_SET_TYPE_IMM = 0x10u, + REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x20u, + REBASE_OPCODE_ADD_ADDR_ULEB = 0x30u, + REBASE_OPCODE_ADD_ADDR_IMM_SCALED = 0x40u, + REBASE_OPCODE_DO_REBASE_IMM_TIMES = 0x50u, + REBASE_OPCODE_DO_REBASE_ULEB_TIMES = 0x60u, + REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB = 0x70u, + REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80u + }; + + enum BindType { + BIND_TYPE_POINTER = 1u, + BIND_TYPE_TEXT_ABSOLUTE32 = 2u, + BIND_TYPE_TEXT_PCREL32 = 3u + }; + enum BindSpecialDylib { + BIND_SPECIAL_DYLIB_SELF = 0, + BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1, + BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2 + }; + + enum { + BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1u, + BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8u, + BIND_OPCODE_MASK = 0xF0u, + BIND_IMMEDIATE_MASK = 0x0Fu + }; + + enum BindOpcode { + BIND_OPCODE_DONE = 0x00u, + BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10u, + BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20u, + BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30u, + BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40u, + BIND_OPCODE_SET_TYPE_IMM = 0x50u, + BIND_OPCODE_SET_ADDEND_SLEB = 0x60u, + BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70u, + BIND_OPCODE_ADD_ADDR_ULEB = 0x80u, + BIND_OPCODE_DO_BIND = 0x90u, + BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0u, + BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0u, + BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0u + }; + + enum { + EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03u, + EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04u, + EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08u, + EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10u + }; + + enum ExportSymbolKind { + EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00u, + EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01u + }; + + + enum { // Constant masks for the "n_type" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 - NlistMaskStab = 0xe0, // N_STAB - NlistMaskPrivateExternal = 0x10, // N_PEXT - NlistMaskType = 0x0e, // N_TYPE - NlistMaskExternal = 0x01, // N_EXT + N_STAB = 0xe0, + N_PEXT = 0x10, + N_TYPE = 0x0e, + N_EXT = 0x01 + }; + enum NListType { // Constants for the "n_type & N_TYPE" llvm::MachO::nlist and // llvm::MachO::nlist_64 - NListTypeUndefined = 0x0u, // N_UNDF - NListTypeAbsolute = 0x2u, // N_ABS - NListTypeSection = 0xeu, // N_SECT - NListTypePreboundUndefined = 0xcu, // N_PBUD - NListTypeIndirect = 0xau, // N_INDR + N_UNDF = 0x0u, + N_ABS = 0x2u, + N_SECT = 0xeu, + N_PBUD = 0xcu, + N_INDR = 0xau + }; - // Constant masks for the "n_sect" field in llvm::MachO::nlist and + enum SectionOrdinal { + // Constants for the "n_sect" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 - NListSectionNoSection = 0u, // NO_SECT - NListSectionMaxSection = 0xffu, // MAX_SECT + NO_SECT = 0u, + MAX_SECT = 0xffu + }; - NListDescWeakRef = 0x40u, - NListDescWeakDef = 0x80u, + enum { + // Constant masks for the "n_desc" field in llvm::MachO::nlist and + // llvm::MachO::nlist_64 + N_ARM_THUMB_DEF = 0x0008u, + N_NO_DEAD_STRIP = 0x0020u, + N_WEAK_REF = 0x0040u, + N_WEAK_DEF = 0x0080u, + N_SYMBOL_RESOLVER = 0x0100u + }; + enum StabType { // Constant values for the "n_type" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 when "(n_type & NlistMaskStab) != 0" - StabGlobalSymbol = 0x20u, // N_GSYM - StabFunctionName = 0x22u, // N_FNAME - StabFunction = 0x24u, // N_FUN - StabStaticSymbol = 0x26u, // N_STSYM - StabLocalCommon = 0x28u, // N_LCSYM - StabBeginSymbol = 0x2Eu, // N_BNSYM - StabSourceFileOptions = 0x3Cu, // N_OPT - StabRegisterSymbol = 0x40u, // N_RSYM - StabSourceLine = 0x44u, // N_SLINE - StabEndSymbol = 0x4Eu, // N_ENSYM - StabStructureType = 0x60u, // N_SSYM - StabSourceFileName = 0x64u, // N_SO - StabObjectFileName = 0x66u, // N_OSO - StabLocalSymbol = 0x80u, // N_LSYM - StabBeginIncludeFileName = 0x82u, // N_BINCL - StabIncludeFileName = 0x84u, // N_SOL - StabCompilerParameters = 0x86u, // N_PARAMS - StabCompilerVersion = 0x88u, // N_VERSION - StabCompilerOptLevel = 0x8Au, // N_OLEVEL - StabParameter = 0xA0u, // N_PSYM - StabEndIncludeFile = 0xA2u, // N_EINCL - StabAlternateEntry = 0xA4u, // N_ENTRY - StabLeftBracket = 0xC0u, // N_LBRAC - StabDeletedIncludeFile = 0xC2u, // N_EXCL - StabRightBracket = 0xE0u, // N_RBRAC - StabBeginCommon = 0xE2u, // N_BCOMM - StabEndCommon = 0xE4u, // N_ECOMM - StabEndCommonLocal = 0xE8u, // N_ECOML - StabLength = 0xFEu // N_LENG - + N_GSYM = 0x20u, + N_FNAME = 0x22u, + N_FUN = 0x24u, + N_STSYM = 0x26u, + N_LCSYM = 0x28u, + N_BNSYM = 0x2Eu, + N_OPT = 0x3Cu, + N_RSYM = 0x40u, + N_SLINE = 0x44u, + N_ENSYM = 0x4Eu, + N_SSYM = 0x60u, + N_SO = 0x64u, + N_OSO = 0x66u, + N_LSYM = 0x80u, + N_BINCL = 0x82u, + N_SOL = 0x84u, + N_PARAMS = 0x86u, + N_VERSION = 0x88u, + N_OLEVEL = 0x8Au, + N_PSYM = 0xA0u, + N_EINCL = 0xA2u, + N_ENTRY = 0xA4u, + N_LBRAC = 0xC0u, + N_EXCL = 0xC2u, + N_RBRAC = 0xE0u, + N_BCOMM = 0xE2u, + N_ECOMM = 0xE4u, + N_ECOML = 0xE8u, + N_LENG = 0xFEu + }; + + enum LLVM_ENUM_INT_TYPE(uint32_t) { + // Constant values for the r_symbolnum field in an + // llvm::MachO::relocation_info structure when r_extern is 0. + R_ABS = 0, + + // Constant bits for the r_address field in an + // llvm::MachO::relocation_info structure. + R_SCATTERED = 0x80000000 + }; + + enum RelocationInfoType { + // Constant values for the r_type field in an + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + GENERIC_RELOC_VANILLA = 0, + GENERIC_RELOC_PAIR = 1, + GENERIC_RELOC_SECTDIFF = 2, + GENERIC_RELOC_PB_LA_PTR = 3, + GENERIC_RELOC_LOCAL_SECTDIFF = 4, + GENERIC_RELOC_TLV = 5, + + // Constant values for the r_type field in a PowerPC architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + PPC_RELOC_VANILLA = GENERIC_RELOC_VANILLA, + PPC_RELOC_PAIR = GENERIC_RELOC_PAIR, + PPC_RELOC_BR14 = 2, + PPC_RELOC_BR24 = 3, + PPC_RELOC_HI16 = 4, + PPC_RELOC_LO16 = 5, + PPC_RELOC_HA16 = 6, + PPC_RELOC_LO14 = 7, + PPC_RELOC_SECTDIFF = 8, + PPC_RELOC_PB_LA_PTR = 9, + PPC_RELOC_HI16_SECTDIFF = 10, + PPC_RELOC_LO16_SECTDIFF = 11, + PPC_RELOC_HA16_SECTDIFF = 12, + PPC_RELOC_JBSR = 13, + PPC_RELOC_LO14_SECTDIFF = 14, + PPC_RELOC_LOCAL_SECTDIFF = 15, + + // Constant values for the r_type field in an ARM architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + ARM_RELOC_VANILLA = GENERIC_RELOC_VANILLA, + ARM_RELOC_PAIR = GENERIC_RELOC_PAIR, + ARM_RELOC_SECTDIFF = GENERIC_RELOC_SECTDIFF, + ARM_RELOC_LOCAL_SECTDIFF = 3, + ARM_RELOC_PB_LA_PTR = 4, + ARM_RELOC_BR24 = 5, + ARM_THUMB_RELOC_BR22 = 6, + ARM_THUMB_32BIT_BRANCH = 7, // obsolete + ARM_RELOC_HALF = 8, + ARM_RELOC_HALF_SECTDIFF = 9, + + // Constant values for the r_type field in an x86_64 architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure + X86_64_RELOC_UNSIGNED = 0, + X86_64_RELOC_SIGNED = 1, + X86_64_RELOC_BRANCH = 2, + X86_64_RELOC_GOT_LOAD = 3, + X86_64_RELOC_GOT = 4, + X86_64_RELOC_SUBTRACTOR = 5, + X86_64_RELOC_SIGNED_1 = 6, + X86_64_RELOC_SIGNED_2 = 7, + X86_64_RELOC_SIGNED_4 = 8, + X86_64_RELOC_TLV = 9 + }; + + // Values for segment_command.initprot. + // From <mach/vm_prot.h> + enum { + VM_PROT_READ = 0x1, + VM_PROT_WRITE = 0x2, + VM_PROT_EXECUTE = 0x4 }; + // Structs from <mach-o/loader.h> struct mach_header { @@ -572,6 +718,18 @@ namespace llvm { uint32_t datasize; }; + struct data_in_code_entry { + uint32_t offset; + uint16_t length; + uint16_t kind; + }; + + struct source_version_command { + uint32_t cmd; + uint32_t cmdsize; + uint64_t version; + }; + struct encryption_info_command { uint32_t cmd; uint32_t cmdsize; @@ -602,6 +760,12 @@ namespace llvm { uint32_t export_size; }; + struct linker_options_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t count; + }; + struct symseg_command { uint32_t cmd; uint32_t cmdsize; @@ -621,6 +785,31 @@ namespace llvm { uint32_t header_addr; }; + struct tlv_descriptor_32 { + uint32_t thunk; + uint32_t key; + uint32_t offset; + }; + + struct tlv_descriptor_64 { + uint64_t thunk; + uint64_t key; + uint64_t offset; + }; + + struct tlv_descriptor { + uintptr_t thunk; + uintptr_t key; + uintptr_t offset; + }; + + struct entry_point_command { + uint32_t cmd; + uint32_t cmdsize; + uint64_t entryoff; + uint64_t stacksize; + }; + // Structs from <mach-o/fat.h> struct fat_header { @@ -636,7 +825,39 @@ namespace llvm { uint32_t align; }; - // Structs from <mach-o/fat.h> + // Structs from <mach-o/reloc.h> + struct relocation_info { + int32_t r_address; + uint32_t r_symbolnum:24, + r_pcrel:1, + r_length:2, + r_extern:1, + r_type:4; + }; + + struct scattered_relocation_info { +#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN) + uint32_t r_scattered:1, + r_pcrel:1, + r_length:2, + r_type:4, + r_address:24; +#else + uint32_t r_address:24, + r_type:4, + r_length:2, + r_pcrel:1, + r_scattered:1; +#endif + int32_t r_value; + }; + + // Structs NOT from <mach-o/reloc.h>, but that make LLVM's life easier + struct any_relocation_info { + uint32_t r_word0, r_word1; + }; + + // Structs from <mach-o/nlist.h> struct nlist { uint32_t n_strx; uint8_t n_type; @@ -655,58 +876,132 @@ namespace llvm { // Get/Set functions from <mach-o/nlist.h> - static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) - { + static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) { return (((n_desc) >> 8u) & 0xffu); } - static inline void SET_LIBRARY_ORDINAL(uint16_t &n_desc, uint8_t ordinal) - { + static inline void SET_LIBRARY_ORDINAL(uint16_t &n_desc, uint8_t ordinal) { n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)); } - static inline uint8_t GET_COMM_ALIGN (uint16_t n_desc) - { + static inline uint8_t GET_COMM_ALIGN (uint16_t n_desc) { return (n_desc >> 8u) & 0x0fu; } - static inline void SET_COMM_ALIGN (uint16_t &n_desc, uint8_t align) - { + static inline void SET_COMM_ALIGN (uint16_t &n_desc, uint8_t align) { n_desc = ((n_desc & 0xf0ffu) | ((align & 0x0fu) << 8u)); } // Enums from <mach/machine.h> - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // Capability bits used in the definition of cpu_type. - CPUArchMask = 0xff000000, // Mask for architecture bits - CPUArchABI64 = 0x01000000, // 64 bit ABI - - // Constants for the cputype field. - CPUTypeI386 = 7, - CPUTypeX86_64 = CPUTypeI386 | CPUArchABI64, - CPUTypeARM = 12, - CPUTypeSPARC = 14, - CPUTypePowerPC = 18, - CPUTypePowerPC64 = CPUTypePowerPC | CPUArchABI64, - - - // Constants for the cpusubtype field. - - // X86 - CPUSubType_I386_ALL = 3, - CPUSubType_X86_64_ALL = 3, - - // ARM - CPUSubType_ARM_ALL = 0, - CPUSubType_ARM_V4T = 5, - CPUSubType_ARM_V5 = 7, - CPUSubType_ARM_V6 = 6, - CPUSubType_ARM_V7 = 9, - - // PowerPC - CPUSubType_POWERPC_ALL = 0, - - CPUSubType_SPARC_ALL = 0 + CPU_ARCH_MASK = 0xff000000, // Mask for architecture bits + CPU_ARCH_ABI64 = 0x01000000 // 64 bit ABI + }; + + // Constants for the cputype field. + enum CPUType { + CPU_TYPE_ANY = -1, + CPU_TYPE_X86 = 7, + CPU_TYPE_I386 = CPU_TYPE_X86, + CPU_TYPE_X86_64 = CPU_TYPE_X86 | CPU_ARCH_ABI64, + /* CPU_TYPE_MIPS = 8, */ + CPU_TYPE_MC98000 = 10, // Old Motorola PowerPC + CPU_TYPE_ARM = 12, + CPU_TYPE_SPARC = 14, + CPU_TYPE_POWERPC = 18, + CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 + }; + + enum LLVM_ENUM_INT_TYPE(uint32_t) { + // Capability bits used in the definition of cpusubtype. + CPU_SUB_TYPE_MASK = 0xff000000, // Mask for architecture bits + CPU_SUB_TYPE_LIB64 = 0x80000000, // 64 bit libraries + + // Special CPU subtype constants. + CPU_SUBTYPE_MULTIPLE = ~0u + }; + + // Constants for the cpusubtype field. + enum CPUSubTypeX86 { + CPU_SUBTYPE_I386_ALL = 3, + CPU_SUBTYPE_386 = 3, + CPU_SUBTYPE_486 = 4, + CPU_SUBTYPE_486SX = 0x84, + CPU_SUBTYPE_586 = 5, + CPU_SUBTYPE_PENT = CPU_SUBTYPE_586, + CPU_SUBTYPE_PENTPRO = 0x16, + CPU_SUBTYPE_PENTII_M3 = 0x36, + CPU_SUBTYPE_PENTII_M5 = 0x56, + CPU_SUBTYPE_CELERON = 0x67, + CPU_SUBTYPE_CELERON_MOBILE = 0x77, + CPU_SUBTYPE_PENTIUM_3 = 0x08, + CPU_SUBTYPE_PENTIUM_3_M = 0x18, + CPU_SUBTYPE_PENTIUM_3_XEON = 0x28, + CPU_SUBTYPE_PENTIUM_M = 0x09, + CPU_SUBTYPE_PENTIUM_4 = 0x0a, + CPU_SUBTYPE_PENTIUM_4_M = 0x1a, + CPU_SUBTYPE_ITANIUM = 0x0b, + CPU_SUBTYPE_ITANIUM_2 = 0x1b, + CPU_SUBTYPE_XEON = 0x0c, + CPU_SUBTYPE_XEON_MP = 0x1c, + + CPU_SUBTYPE_X86_ALL = 3, + CPU_SUBTYPE_X86_64_ALL = 3, + CPU_SUBTYPE_X86_ARCH1 = 4, + CPU_SUBTYPE_X86_64_H = 8 + }; + static inline int CPU_SUBTYPE_INTEL(int Family, int Model) { + return Family | (Model << 4); + } + static inline int CPU_SUBTYPE_INTEL_FAMILY(CPUSubTypeX86 ST) { + return ((int)ST) & 0x0f; + } + static inline int CPU_SUBTYPE_INTEL_MODEL(CPUSubTypeX86 ST) { + return ((int)ST) >> 4; + } + enum { + CPU_SUBTYPE_INTEL_FAMILY_MAX = 15, + CPU_SUBTYPE_INTEL_MODEL_ALL = 0 + }; + + enum CPUSubTypeARM { + CPU_SUBTYPE_ARM_ALL = 0, + CPU_SUBTYPE_ARM_V4T = 5, + CPU_SUBTYPE_ARM_V6 = 6, + CPU_SUBTYPE_ARM_V5 = 7, + CPU_SUBTYPE_ARM_V5TEJ = 7, + CPU_SUBTYPE_ARM_XSCALE = 8, + CPU_SUBTYPE_ARM_V7 = 9, + CPU_SUBTYPE_ARM_V7F = 10, + CPU_SUBTYPE_ARM_V7S = 11, + CPU_SUBTYPE_ARM_V7K = 12, + CPU_SUBTYPE_ARM_V6M = 14, + CPU_SUBTYPE_ARM_V7M = 15, + CPU_SUBTYPE_ARM_V7EM = 16 + }; + + enum CPUSubTypeSPARC { + CPU_SUBTYPE_SPARC_ALL = 0 + }; + + enum CPUSubTypePowerPC { + CPU_SUBTYPE_POWERPC_ALL = 0, + CPU_SUBTYPE_POWERPC_601 = 1, + CPU_SUBTYPE_POWERPC_602 = 2, + CPU_SUBTYPE_POWERPC_603 = 3, + CPU_SUBTYPE_POWERPC_603e = 4, + CPU_SUBTYPE_POWERPC_603ev = 5, + CPU_SUBTYPE_POWERPC_604 = 6, + CPU_SUBTYPE_POWERPC_604e = 7, + CPU_SUBTYPE_POWERPC_620 = 8, + CPU_SUBTYPE_POWERPC_750 = 9, + CPU_SUBTYPE_POWERPC_7400 = 10, + CPU_SUBTYPE_POWERPC_7450 = 11, + CPU_SUBTYPE_POWERPC_970 = 100, + + CPU_SUBTYPE_MC980000_ALL = CPU_SUBTYPE_POWERPC_ALL, + CPU_SUBTYPE_MC98601 = CPU_SUBTYPE_POWERPC_601 }; } // end namespace MachO } // end namespace llvm diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index 4171d1b..5587618 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -99,7 +99,6 @@ public: /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. void llvm_shutdown(); - /// llvm_shutdown_obj - This is a simple helper class that calls /// llvm_shutdown() when it is destroyed. struct llvm_shutdown_obj { diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 00c6ad7..ff41608 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -21,7 +21,8 @@ #include <cstring> #ifdef _MSC_VER -# include <intrin.h> +#include <intrin.h> +#include <limits> #endif namespace llvm { @@ -603,6 +604,13 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) { return int64_t(X << (64 - B)) >> (64 - B); } +#if defined(_MSC_VER) + // Visual Studio defines the HUGE_VAL class of macros using purposeful + // constant arithmetic overflow, which it then warns on when encountered. + const float huge_valf = std::numeric_limits<float>::infinity(); +#else + const float huge_valf = HUGE_VALF; +#endif } // End llvm namespace #endif diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 4f28da4..ff22fb6 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -14,7 +14,7 @@ #ifndef LLVM_SUPPORT_MEMORYBUFFER_H #define LLVM_SUPPORT_MEMORYBUFFER_H -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" @@ -66,11 +66,7 @@ public: /// MemoryBuffer if successful, otherwise returning null. If FileSize is /// specified, this means that the client knows that the file exists and that /// it has the specified size. - static error_code getFile(StringRef Filename, OwningPtr<MemoryBuffer> &result, - int64_t FileSize = -1, - bool RequiresNullTerminator = true); - static error_code getFile(const char *Filename, - OwningPtr<MemoryBuffer> &result, + static error_code getFile(Twine Filename, OwningPtr<MemoryBuffer> &result, int64_t FileSize = -1, bool RequiresNullTerminator = true); diff --git a/include/llvm/Support/PassNameParser.h b/include/llvm/Support/PassNameParser.h index a73dc8f..c0914b1 100644 --- a/include/llvm/Support/PassNameParser.h +++ b/include/llvm/Support/PassNameParser.h @@ -86,10 +86,9 @@ public: private: // ValLessThan - Provide a sorting comparator for Values elements... - static int ValLessThan(const void *VT1, const void *VT2) { - typedef PassNameParser::OptionInfo ValType; - return std::strcmp(static_cast<const ValType *>(VT1)->Name, - static_cast<const ValType *>(VT2)->Name); + static int ValLessThan(const PassNameParser::OptionInfo *VT1, + const PassNameParser::OptionInfo *VT2) { + return std::strcmp(VT1->Name, VT2->Name); } }; diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h index f9a65e5..b2afe1b 100644 --- a/include/llvm/Support/Path.h +++ b/include/llvm/Support/Path.h @@ -173,6 +173,13 @@ void append(SmallVectorImpl<char> &path, /// @param result Holds the result of the transformation. void native(const Twine &path, SmallVectorImpl<char> &result); +/// Convert path to the native form in place. This is used to give paths to +/// users and operating system calls in the platform's normal way. For example, +/// on Windows all '/' are converted to '\'. +/// +/// @param path A path that is transformed to native format. +void native(SmallVectorImpl<char> &path); + /// @} /// @name Lexical Observers /// @{ diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index b1732b2..240bb81 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -1041,7 +1041,7 @@ inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) { /// Intrinsic matchers. struct IntrinsicID_match { unsigned ID; - IntrinsicID_match(unsigned IntrID) : ID(IntrID) { } + IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { } template<typename OpTy> bool match(OpTy *V) { @@ -1080,29 +1080,29 @@ struct m_Intrinsic_Ty<T0, T1, T2, T3> { /// Match intrinsic calls like this: /// m_Intrinsic<Intrinsic::fabs>(m_Value(X)) -template <unsigned IntrID> +template <Intrinsic::ID IntrID> inline IntrinsicID_match m_Intrinsic() { return IntrinsicID_match(IntrID); } -template<unsigned IntrID, typename T0> +template<Intrinsic::ID IntrID, typename T0> inline typename m_Intrinsic_Ty<T0>::Ty m_Intrinsic(const T0 &Op0) { return m_CombineAnd(m_Intrinsic<IntrID>(), m_Argument<0>(Op0)); } -template<unsigned IntrID, typename T0, typename T1> +template<Intrinsic::ID IntrID, typename T0, typename T1> inline typename m_Intrinsic_Ty<T0, T1>::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1) { return m_CombineAnd(m_Intrinsic<IntrID>(Op0), m_Argument<1>(Op1)); } -template<unsigned IntrID, typename T0, typename T1, typename T2> +template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2> inline typename m_Intrinsic_Ty<T0, T1, T2>::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1), m_Argument<2>(Op2)); } -template<unsigned IntrID, typename T0, typename T1, typename T2, typename T3> +template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2, typename T3> inline typename m_Intrinsic_Ty<T0, T1, T2, T3>::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1, Op2), m_Argument<3>(Op3)); diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h index 2122e06..4f68fca 100644 --- a/include/llvm/Support/PrettyStackTrace.h +++ b/include/llvm/Support/PrettyStackTrace.h @@ -21,11 +21,7 @@ namespace llvm { class raw_ostream; - /// DisablePrettyStackTrace - Set this to true to disable this module. This - /// might be necessary if the host application installs its own signal - /// handlers which conflict with the ones installed by this module. - /// Defaults to false. - extern bool DisablePrettyStackTrace; + void EnablePrettyStackTrace(); /// PrettyStackTraceEntry - This class is used to represent a frame of the /// "pretty" stack trace that is dumped when a program crashes. You can define @@ -64,7 +60,9 @@ namespace llvm { const char *const *ArgV; public: PrettyStackTraceProgram(int argc, const char * const*argv) - : ArgC(argc), ArgV(argv) {} + : ArgC(argc), ArgV(argv) { + EnablePrettyStackTrace(); + } virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; }; diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index 0baf7b9..2172036 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -25,11 +25,17 @@ #ifndef LLVM_SUPPORT_PROCESS_H #define LLVM_SUPPORT_PROCESS_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/system_error.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/TimeValue.h" namespace llvm { +class StringRef; + namespace sys { class self_process; @@ -155,22 +161,24 @@ public: static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, TimeValue &sys_time); - /// This static function will return the process' current user id number. - /// Not all operating systems support this feature. Where it is not - /// supported, the function should return 65536 as the value. - static int GetCurrentUserId(); - - /// This static function will return the process' current group id number. - /// Not all operating systems support this feature. Where it is not - /// supported, the function should return 65536 as the value. - static int GetCurrentGroupId(); - /// This function makes the necessary calls to the operating system to /// prevent core files or any other kind of large memory dumps that can /// occur when a program fails. /// @brief Prevent core file generation. static void PreventCoreFiles(); + // This function returns the environment variable \arg name's value as a UTF-8 + // string. \arg Name is assumed to be in UTF-8 encoding too. + static Optional<std::string> GetEnv(StringRef name); + + /// This function returns a SmallVector containing the arguments passed from + /// the operating system to the program. This function expects to be handed + /// the vector passed in from main. + static error_code + GetArgumentVector(SmallVectorImpl<const char *> &Args, + ArrayRef<const char *> ArgsFromMain, + SpecificBumpPtrAllocator<char> &ArgAllocator); + /// This function determines if the standard input is connected directly /// to a user's input (keyboard probably), rather than coming from a file /// or pipe. @@ -219,6 +227,12 @@ public: /// terminal, this function returns false. static bool StandardErrHasColors(); + /// Enables or disables whether ANSI escape sequences are used to output + /// colors. This only has an effect on Windows. + /// Note: Setting this option is not thread-safe and should only be done + /// during initialization. + static void UseANSIEscapeCodes(bool enable); + /// Whether changing colors requires the output to be flushed. /// This is needed on systems that don't support escape sequences for /// changing colors. diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 5134351..00571a4 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -30,6 +30,28 @@ namespace sys { const char EnvPathSeparator = ';'; #endif +/// @brief This struct encapsulates information about a process. +struct ProcessInfo { +#if defined(LLVM_ON_UNIX) + typedef pid_t ProcessId; +#elif defined(LLVM_ON_WIN32) + typedef unsigned long ProcessId; // Must match the type of DWORD on Windows. + typedef void * HANDLE; // Must match the type of HANDLE on Windows. + /// The handle to the process (available on Windows only). + HANDLE ProcessHandle; +#else +#error "ProcessInfo is not defined for this platform!" +#endif + + /// The process identifier. + ProcessId Pid; + + /// The return code, set after execution. + int ReturnCode; + + ProcessInfo(); +}; + /// This static constructor (factory) will attempt to locate a program in /// the operating system's file system using some pre-determined set of /// locations to search (e.g. the PATH on Unix). Paths with slashes are @@ -87,15 +109,41 @@ namespace sys { ///< program. bool *ExecutionFailed = 0); - /// Similar to ExecuteAndWait, but return immediately. - void ExecuteNoWait(StringRef Program, const char **args, const char **env = 0, - const StringRef **redirects = 0, unsigned memoryLimit = 0, - std::string *ErrMsg = 0); + /// Similar to ExecuteAndWait, but returns immediately. + /// @returns The \see ProcessInfo of the newly launced process. + /// \note On Microsoft Windows systems, users will need to either call \see + /// Wait until the process finished execution or win32 CloseHandle() API on + /// ProcessInfo.ProcessHandle to avoid memory leaks. + ProcessInfo + ExecuteNoWait(StringRef Program, const char **args, const char **env = 0, + const StringRef **redirects = 0, unsigned memoryLimit = 0, + std::string *ErrMsg = 0, bool *ExecutionFailed = 0); - // Return true if the given arguments fit within system-specific - // argument length limits. + /// Return true if the given arguments fit within system-specific + /// argument length limits. bool argumentsFitWithinSystemLimits(ArrayRef<const char*> Args); -} + + /// This function waits for the process specified by \p PI to finish. + /// \returns A \see ProcessInfo struct with Pid set to: + /// \li The process id of the child process if the child process has changed + /// state. + /// \li 0 if the child process has not changed state. + /// \note Users of this function should always check the ReturnCode member of + /// the \see ProcessInfo returned from this function. + ProcessInfo Wait( + const ProcessInfo &PI, ///< The child process that should be waited on. + unsigned SecondsToWait, ///< If non-zero, this specifies the amount of + ///< time to wait for the child process to exit. If the time expires, the + ///< child is killed and this function returns. If zero, this function + ///< will perform a non-blocking wait on the child process. + bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits + ///< until child has terminated. + std::string *ErrMsg = 0 ///< If non-zero, provides a pointer to a string + ///< instance in which error messages will be returned. If the string + ///< is non-empty upon return an error occurred while invoking the + ///< program. + ); + } } #endif diff --git a/include/llvm/Support/RecyclingAllocator.h b/include/llvm/Support/RecyclingAllocator.h index f67503f..001d1cf 100644 --- a/include/llvm/Support/RecyclingAllocator.h +++ b/include/llvm/Support/RecyclingAllocator.h @@ -60,9 +60,10 @@ public: } template<class AllocatorType, class T, size_t Size, size_t Align> -inline void *operator new(size_t, +inline void *operator new(size_t size, llvm::RecyclingAllocator<AllocatorType, T, Size, Align> &Allocator) { + assert(size <= Size && "allocation size exceeded"); return Allocator.Allocate(); } diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 5b33d42..dd48974 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -144,11 +144,17 @@ public: /// /// @param ShowColors - Display colored messages if output is a terminal and /// the default error handler is used. - void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, + void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, + const Twine &Msg, ArrayRef<SMRange> Ranges = None, ArrayRef<SMFixIt> FixIts = None, bool ShowColors = true) const; + /// Emits a diagnostic to llvm::errs(). + void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, + ArrayRef<SMRange> Ranges = None, + ArrayRef<SMFixIt> FixIts = None, + bool ShowColors = true) const; /// GetMessage - Return an SMDiagnostic at the specified location with the /// specified string. diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 109b3a2..9ecee3b 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -46,18 +46,18 @@ namespace llvm { class MCRelocationInfo; class MCTargetAsmParser; class TargetMachine; + class MCTargetStreamer; class TargetOptions; class raw_ostream; class formatted_raw_ostream; - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, + MCStreamer *createAsmStreamer(MCContext &Ctx, + MCTargetStreamer *TargetStreamer, + formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, bool useCFI, bool useDwarfDirectory, - MCInstPrinter *InstPrint, - MCCodeEmitter *CE, - MCAsmBackend *TAB, - bool ShowInst); + MCInstPrinter *InstPrint, MCCodeEmitter *CE, + MCAsmBackend *TAB, bool ShowInst); MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx); @@ -104,10 +104,12 @@ namespace llvm { typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, MCStreamer &Streamer); typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, + const MCRegisterInfo &MRI, StringRef TT, StringRef CPU); typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(MCSubtargetInfo &STI, - MCAsmParser &P); + MCAsmParser &P, + const MCInstrInfo &MII); typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, const MCSubtargetInfo &STI); typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, @@ -234,9 +236,9 @@ namespace llvm { MCSymbolizerCtorTy MCSymbolizerCtorFn; public: - Target() : AsmStreamerCtorFn(llvm::createAsmStreamer), - MCRelocationInfoCtorFn(llvm::createMCRelocationInfo), - MCSymbolizerCtorFn(llvm::createMCSymbolizer) {} + Target() + : AsmStreamerCtorFn(0), MCRelocationInfoCtorFn(0), + MCSymbolizerCtorFn(0) {} /// @name Target Information /// @{ @@ -263,27 +265,6 @@ namespace llvm { /// hasMCAsmBackend - Check if this target supports .o generation. bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != 0; } - /// hasAsmParser - Check if this target supports .s parsing. - bool hasMCAsmParser() const { return MCAsmParserCtorFn != 0; } - - /// hasAsmPrinter - Check if this target supports .s printing. - bool hasAsmPrinter() const { return AsmPrinterCtorFn != 0; } - - /// hasMCDisassembler - Check if this target has a disassembler. - bool hasMCDisassembler() const { return MCDisassemblerCtorFn != 0; } - - /// hasMCInstPrinter - Check if this target has an instruction printer. - bool hasMCInstPrinter() const { return MCInstPrinterCtorFn != 0; } - - /// hasMCCodeEmitter - Check if this target supports instruction encoding. - bool hasMCCodeEmitter() const { return MCCodeEmitterCtorFn != 0; } - - /// hasMCObjectStreamer - Check if this target supports streaming to files. - bool hasMCObjectStreamer() const { return MCObjectStreamerCtorFn != 0; } - - /// hasAsmStreamer - Check if this target supports streaming to files. - bool hasAsmStreamer() const { return AsmStreamerCtorFn != 0; } - /// @} /// @name Feature Constructors /// @{ @@ -373,10 +354,11 @@ namespace llvm { /// createMCAsmBackend - Create a target specific assembly parser. /// /// \param Triple The target triple string. - MCAsmBackend *createMCAsmBackend(StringRef Triple, StringRef CPU) const { + MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, + StringRef Triple, StringRef CPU) const { if (!MCAsmBackendCtorFn) return 0; - return MCAsmBackendCtorFn(*this, Triple, CPU); + return MCAsmBackendCtorFn(*this, MRI, Triple, CPU); } /// createMCAsmParser - Create a target specific assembly parser. @@ -384,10 +366,11 @@ namespace llvm { /// \param Parser The target independent parser implementation to use for /// parsing and lexing. MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI, - MCAsmParser &Parser) const { + MCAsmParser &Parser, + const MCInstrInfo &MII) const { if (!MCAsmParserCtorFn) return 0; - return MCAsmParserCtorFn(STI, Parser); + return MCAsmParserCtorFn(STI, Parser, MII); } /// createAsmPrinter - Create a target specific assembly printer pass. This @@ -457,9 +440,13 @@ namespace llvm { MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) const { - // AsmStreamerCtorFn is default to llvm::createAsmStreamer - return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI, - useDwarfDirectory, InstPrint, CE, TAB, ShowInst); + if (AsmStreamerCtorFn) + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI, + useDwarfDirectory, InstPrint, CE, TAB, + ShowInst); + return llvm::createAsmStreamer(Ctx, 0, OS, isVerboseAsm, useLoc, useCFI, + useDwarfDirectory, InstPrint, CE, TAB, + ShowInst); } /// createMCRelocationInfo - Create a target specific MCRelocationInfo. @@ -468,7 +455,10 @@ namespace llvm { /// \param Ctx The target context. MCRelocationInfo * createMCRelocationInfo(StringRef TT, MCContext &Ctx) const { - return MCRelocationInfoCtorFn(TT, Ctx); + MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn + ? MCRelocationInfoCtorFn + : llvm::createMCRelocationInfo; + return Fn(TT, Ctx); } /// createMCSymbolizer - Create a target specific MCSymbolizer. @@ -485,8 +475,9 @@ namespace llvm { LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx, MCRelocationInfo *RelInfo) const { - return MCSymbolizerCtorFn(TT, GetOpInfo, SymbolLookUp, DisInfo, - Ctx, RelInfo); + MCSymbolizerCtorTy Fn = + MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer; + return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo); } /// @} @@ -607,9 +598,7 @@ namespace llvm { /// @param T - The target being registered. /// @param Fn - A function to construct a MCAsmInfo for the target. static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) { - // Ignore duplicate registration. - if (!T.MCAsmInfoCtorFn) - T.MCAsmInfoCtorFn = Fn; + T.MCAsmInfoCtorFn = Fn; } /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the @@ -623,9 +612,7 @@ namespace llvm { /// @param Fn - A function to construct a MCCodeGenInfo for the target. static void RegisterMCCodeGenInfo(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { - // Ignore duplicate registration. - if (!T.MCCodeGenInfoCtorFn) - T.MCCodeGenInfoCtorFn = Fn; + T.MCCodeGenInfoCtorFn = Fn; } /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the @@ -638,18 +625,14 @@ namespace llvm { /// @param T - The target being registered. /// @param Fn - A function to construct a MCInstrInfo for the target. static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) { - // Ignore duplicate registration. - if (!T.MCInstrInfoCtorFn) - T.MCInstrInfoCtorFn = Fn; + T.MCInstrInfoCtorFn = Fn; } /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for /// the given target. static void RegisterMCInstrAnalysis(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) { - // Ignore duplicate registration. - if (!T.MCInstrAnalysisCtorFn) - T.MCInstrAnalysisCtorFn = Fn; + T.MCInstrAnalysisCtorFn = Fn; } /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the @@ -662,9 +645,7 @@ namespace llvm { /// @param T - The target being registered. /// @param Fn - A function to construct a MCRegisterInfo for the target. static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) { - // Ignore duplicate registration. - if (!T.MCRegInfoCtorFn) - T.MCRegInfoCtorFn = Fn; + T.MCRegInfoCtorFn = Fn; } /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for @@ -678,9 +659,7 @@ namespace llvm { /// @param Fn - A function to construct a MCSubtargetInfo for the target. static void RegisterMCSubtargetInfo(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) { - // Ignore duplicate registration. - if (!T.MCSubtargetInfoCtorFn) - T.MCSubtargetInfoCtorFn = Fn; + T.MCSubtargetInfoCtorFn = Fn; } /// RegisterTargetMachine - Register a TargetMachine implementation for the @@ -694,9 +673,7 @@ namespace llvm { /// @param Fn - A function to construct a TargetMachine for the target. static void RegisterTargetMachine(Target &T, Target::TargetMachineCtorTy Fn) { - // Ignore duplicate registration. - if (!T.TargetMachineCtorFn) - T.TargetMachineCtorFn = Fn; + T.TargetMachineCtorFn = Fn; } /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the @@ -709,8 +686,7 @@ namespace llvm { /// @param T - The target being registered. /// @param Fn - A function to construct an AsmBackend for the target. static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) { - if (!T.MCAsmBackendCtorFn) - T.MCAsmBackendCtorFn = Fn; + T.MCAsmBackendCtorFn = Fn; } /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for @@ -723,8 +699,7 @@ namespace llvm { /// @param T - The target being registered. /// @param Fn - A function to construct an MCTargetAsmParser for the target. static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) { - if (!T.MCAsmParserCtorFn) - T.MCAsmParserCtorFn = Fn; + T.MCAsmParserCtorFn = Fn; } /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given @@ -737,9 +712,7 @@ namespace llvm { /// @param T - The target being registered. /// @param Fn - A function to construct an AsmPrinter for the target. static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) { - // Ignore duplicate registration. - if (!T.AsmPrinterCtorFn) - T.AsmPrinterCtorFn = Fn; + T.AsmPrinterCtorFn = Fn; } /// RegisterMCDisassembler - Register a MCDisassembler implementation for @@ -753,8 +726,7 @@ namespace llvm { /// @param Fn - A function to construct an MCDisassembler for the target. static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn) { - if (!T.MCDisassemblerCtorFn) - T.MCDisassemblerCtorFn = Fn; + T.MCDisassemblerCtorFn = Fn; } /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the @@ -768,8 +740,7 @@ namespace llvm { /// @param Fn - A function to construct an MCInstPrinter for the target. static void RegisterMCInstPrinter(Target &T, Target::MCInstPrinterCtorTy Fn) { - if (!T.MCInstPrinterCtorFn) - T.MCInstPrinterCtorFn = Fn; + T.MCInstPrinterCtorFn = Fn; } /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the @@ -783,8 +754,7 @@ namespace llvm { /// @param Fn - A function to construct an MCCodeEmitter for the target. static void RegisterMCCodeEmitter(Target &T, Target::MCCodeEmitterCtorTy Fn) { - if (!T.MCCodeEmitterCtorFn) - T.MCCodeEmitterCtorFn = Fn; + T.MCCodeEmitterCtorFn = Fn; } /// RegisterMCObjectStreamer - Register a object code MCStreamer @@ -798,8 +768,7 @@ namespace llvm { /// @param Fn - A function to construct an MCStreamer for the target. static void RegisterMCObjectStreamer(Target &T, Target::MCObjectStreamerCtorTy Fn) { - if (!T.MCObjectStreamerCtorFn) - T.MCObjectStreamerCtorFn = Fn; + T.MCObjectStreamerCtorFn = Fn; } /// RegisterAsmStreamer - Register an assembly MCStreamer implementation @@ -812,8 +781,7 @@ namespace llvm { /// @param T - The target being registered. /// @param Fn - A function to construct an MCStreamer for the target. static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) { - if (T.AsmStreamerCtorFn == createAsmStreamer) - T.AsmStreamerCtorFn = Fn; + T.AsmStreamerCtorFn = Fn; } /// RegisterMCRelocationInfo - Register an MCRelocationInfo @@ -827,8 +795,7 @@ namespace llvm { /// @param Fn - A function to construct an MCRelocationInfo for the target. static void RegisterMCRelocationInfo(Target &T, Target::MCRelocationInfoCtorTy Fn) { - if (T.MCRelocationInfoCtorFn == llvm::createMCRelocationInfo) - T.MCRelocationInfoCtorFn = Fn; + T.MCRelocationInfoCtorFn = Fn; } /// RegisterMCSymbolizer - Register an MCSymbolizer @@ -842,8 +809,7 @@ namespace llvm { /// @param Fn - A function to construct an MCSymbolizer for the target. static void RegisterMCSymbolizer(Target &T, Target::MCSymbolizerCtorTy Fn) { - if (T.MCSymbolizerCtorFn == llvm::createMCSymbolizer) - T.MCSymbolizerCtorFn = Fn; + T.MCSymbolizerCtorFn = Fn; } /// @} @@ -1118,9 +1084,10 @@ namespace llvm { } private: - static MCAsmBackend *Allocator(const Target &T, StringRef Triple, - StringRef CPU) { - return new MCAsmBackendImpl(T, Triple, CPU); + static MCAsmBackend *Allocator(const Target &T, + const MCRegisterInfo &MRI, + StringRef Triple, StringRef CPU) { + return new MCAsmBackendImpl(T, MRI, Triple, CPU); } }; @@ -1139,8 +1106,9 @@ namespace llvm { } private: - static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P) { - return new MCAsmParserImpl(STI, P); + static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P, + const MCInstrInfo &MII) { + return new MCAsmParserImpl(STI, P, MII); } }; diff --git a/include/llvm/Support/Unicode.h b/include/llvm/Support/Unicode.h new file mode 100644 index 0000000..e6a52c4 --- /dev/null +++ b/include/llvm/Support/Unicode.h @@ -0,0 +1,62 @@ +//===- llvm/Support/Unicode.h - Unicode character properties -*- C++ -*-=====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines functions that allow querying certain properties of Unicode +// characters. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" + +namespace llvm { +namespace sys { +namespace unicode { + +enum ColumnWidthErrors { + ErrorInvalidUTF8 = -2, + ErrorNonPrintableCharacter = -1 +}; + +/// Determines if a character is likely to be displayed correctly on the +/// terminal. Exact implementation would have to depend on the specific +/// terminal, so we define the semantic that should be suitable for generic case +/// of a terminal capable to output Unicode characters. +/// +/// All characters from the Unicode code point range are considered printable +/// except for: +/// * C0 and C1 control character ranges; +/// * default ignorable code points as per 5.21 of +/// http://www.unicode.org/versions/Unicode6.2.0/UnicodeStandard-6.2.pdf +/// except for U+00AD SOFT HYPHEN, as it's actually displayed on most +/// terminals; +/// * format characters (category = Cf); +/// * surrogates (category = Cs); +/// * unassigned characters (category = Cn). +/// \return true if the character is considered printable. +bool isPrintable(int UCS); + +/// Gets the number of positions the UTF8-encoded \p Text is likely to occupy +/// when output on a terminal ("character width"). This depends on the +/// implementation of the terminal, and there's no standard definition of +/// character width. +/// +/// The implementation defines it in a way that is expected to be compatible +/// with a generic Unicode-capable terminal. +/// +/// \return Character width: +/// * ErrorNonPrintableCharacter (-1) if \p Text contains non-printable +/// characters (as identified by isPrintable); +/// * 0 for each non-spacing and enclosing combining mark; +/// * 2 for each CJK character excluding halfwidth forms; +/// * 1 for each of the remaining characters. +int columnWidthUTF8(StringRef Text); + +} // namespace unicode +} // namespace sys +} // namespace llvm diff --git a/include/llvm/Support/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h index 4a4d988..86faa38 100644 --- a/include/llvm/Support/UnicodeCharRanges.h +++ b/include/llvm/Support/UnicodeCharRanges.h @@ -17,82 +17,80 @@ #include "llvm/Support/MutexGuard.h" #include "llvm/Support/raw_ostream.h" -namespace { +#include <algorithm> +namespace llvm { +namespace sys { + +/// \brief Represents a closed range of Unicode code points [Lower, Upper]. struct UnicodeCharRange { uint32_t Lower; uint32_t Upper; }; -typedef llvm::ArrayRef<UnicodeCharRange> UnicodeCharSet; -/// Returns true if each of the ranges in \p CharSet is a proper closed range -/// [min, max], and if the ranges themselves are ordered and non-overlapping. -static inline bool isValidCharSet(UnicodeCharSet CharSet) { -#ifndef NDEBUG - static llvm::SmallPtrSet<const UnicodeCharRange *, 16> Validated; - static llvm::sys::Mutex ValidationMutex; +inline bool operator<(uint32_t Value, UnicodeCharRange Range) { + return Value < Range.Lower; +} +inline bool operator<(UnicodeCharRange Range, uint32_t Value) { + return Range.Upper < Value; +} - // Check the validation cache. - { - llvm::MutexGuard Guard(ValidationMutex); - if (Validated.count(CharSet.data())) - return true; - } +/// \brief Holds a reference to an ordered array of UnicodeCharRange and allows +/// to quickly check if a code point is contained in the set represented by this +/// array. +class UnicodeCharSet { +public: + typedef llvm::ArrayRef<UnicodeCharRange> CharRanges; - // Walk through the ranges. - uint32_t Prev = 0; - for (UnicodeCharSet::iterator I = CharSet.begin(), E = CharSet.end(); - I != E; ++I) { - if (I != CharSet.begin() && Prev >= I->Lower) { - DEBUG(llvm::dbgs() << "Upper bound 0x"); - DEBUG(llvm::dbgs().write_hex(Prev)); - DEBUG(llvm::dbgs() << " should be less than succeeding lower bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Lower) << "\n"); - return false; - } - if (I->Upper < I->Lower) { - DEBUG(llvm::dbgs() << "Upper bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Lower)); - DEBUG(llvm::dbgs() << " should not be less than lower bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Upper) << "\n"); - return false; - } - Prev = I->Upper; + /// \brief Constructs a UnicodeCharSet instance from an array of + /// UnicodeCharRanges. + /// + /// Array pointed by \p Ranges should have the lifetime at least as long as + /// the UnicodeCharSet instance, and should not change. Array is validated by + /// the constructor, so it makes sense to create as few UnicodeCharSet + /// instances per each array of ranges, as possible. + UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) { + assert(rangesAreValid()); } - // Update the validation cache. - { - llvm::MutexGuard Guard(ValidationMutex); - Validated.insert(CharSet.data()); + /// \brief Returns true if the character set contains the Unicode code point + /// \p C. + bool contains(uint32_t C) const { + return std::binary_search(Ranges.begin(), Ranges.end(), C); } -#endif - return true; -} - -} // namespace +private: + /// \brief Returns true if each of the ranges is a proper closed range + /// [min, max], and if the ranges themselves are ordered and non-overlapping. + bool rangesAreValid() const { + uint32_t Prev = 0; + for (CharRanges::const_iterator I = Ranges.begin(), E = Ranges.end(); + I != E; ++I) { + if (I != Ranges.begin() && Prev >= I->Lower) { + DEBUG(llvm::dbgs() << "Upper bound 0x"); + DEBUG(llvm::dbgs().write_hex(Prev)); + DEBUG(llvm::dbgs() << " should be less than succeeding lower bound 0x"); + DEBUG(llvm::dbgs().write_hex(I->Lower) << "\n"); + return false; + } + if (I->Upper < I->Lower) { + DEBUG(llvm::dbgs() << "Upper bound 0x"); + DEBUG(llvm::dbgs().write_hex(I->Lower)); + DEBUG(llvm::dbgs() << " should not be less than lower bound 0x"); + DEBUG(llvm::dbgs().write_hex(I->Upper) << "\n"); + return false; + } + Prev = I->Upper; + } -/// Returns true if the Unicode code point \p C is within the set of -/// characters specified by \p CharSet. -LLVM_READONLY static inline bool isCharInSet(uint32_t C, - UnicodeCharSet CharSet) { - assert(isValidCharSet(CharSet)); + return true; + } - size_t LowPoint = 0; - size_t HighPoint = CharSet.size(); + const CharRanges Ranges; +}; - // Binary search the set of char ranges. - while (HighPoint != LowPoint) { - size_t MidPoint = (HighPoint + LowPoint) / 2; - if (C < CharSet[MidPoint].Lower) - HighPoint = MidPoint; - else if (C > CharSet[MidPoint].Upper) - LowPoint = MidPoint + 1; - else - return true; - } +} // namespace sys +} // namespace llvm - return false; -} #endif // LLVM_SUPPORT_UNICODECHARRANGES_H diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h index a1397db..7ae40af 100644 --- a/include/llvm/Support/Valgrind.h +++ b/include/llvm/Support/Valgrind.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_VALGRIND_H -#define LLVM_SYSTEM_VALGRIND_H +#ifndef LLVM_SUPPORT_VALGRIND_H +#define LLVM_SUPPORT_VALGRIND_H #include "llvm/Config/llvm-config.h" #include "llvm/Support/Compiler.h" diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index b49341c..bc02ba3 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -339,6 +339,7 @@ public: /// rearrange itself when the pointer changes). Unlike ValueHandleBase, this /// class has a vtable and a virtual destructor. class CallbackVH : public ValueHandleBase { + virtual void anchor(); protected: CallbackVH(const CallbackVH &RHS) : ValueHandleBase(Callback, RHS) {} @@ -365,13 +366,13 @@ public: /// /// All implementations must remove the reference from this object to the /// Value that's being destroyed. - virtual void deleted(); + virtual void deleted() { setValPtr(NULL); } /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, /// _before_ any of the uses have actually been replaced. If WeakVH were /// implemented as a CallbackVH, it would use this method to call /// setValPtr(new_value). AssertingVH would do nothing in this method. - virtual void allUsesReplacedWith(Value *); + virtual void allUsesReplacedWith(Value *) {} }; } // End llvm namespace diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 338bb4b..7020449 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -43,6 +43,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/SMLoc.h" + +#include <map> #include <limits> #include <utility> @@ -99,13 +101,11 @@ private: OwningPtr<Document> CurrentDoc; friend class Document; - - /// @brief Validate a %YAML x.x directive. - void handleYAMLDirective(const Token &); }; /// @brief Abstract base class for all Nodes. class Node { + virtual void anchor(); public: enum NodeKind { NK_Null, @@ -116,12 +116,21 @@ public: NK_Alias }; - Node(unsigned int Type, OwningPtr<Document>&, StringRef Anchor); + Node(unsigned int Type, OwningPtr<Document> &, StringRef Anchor, + StringRef Tag); /// @brief Get the value of the anchor attached to this node. If it does not /// have one, getAnchor().size() will be 0. StringRef getAnchor() const { return Anchor; } + /// \brief Get the tag as it was written in the document. This does not + /// perform tag resolution. + StringRef getRawTag() const { return Tag; } + + /// \brief Get the verbatium tag for a given Node. This performs tag resoluton + /// and substitution. + std::string getVerbatimTag() const; + SMRange getSourceRange() const { return SourceRange; } void setSourceRange(SMRange SR) { SourceRange = SR; } @@ -158,6 +167,8 @@ protected: private: unsigned int TypeID; StringRef Anchor; + /// \brief The tag as typed in the document. + StringRef Tag; }; /// @brief A null value. @@ -165,8 +176,10 @@ private: /// Example: /// !!null null class NullNode : public Node { + virtual void anchor(); public: - NullNode(OwningPtr<Document> &D) : Node(NK_Null, D, StringRef()) {} + NullNode(OwningPtr<Document> &D) + : Node(NK_Null, D, StringRef(), StringRef()) {} static inline bool classof(const Node *N) { return N->getType() == NK_Null; @@ -179,10 +192,11 @@ public: /// Example: /// Adena class ScalarNode : public Node { + virtual void anchor(); public: - ScalarNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Val) - : Node(NK_Scalar, D, Anchor) - , Value(Val) { + ScalarNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + StringRef Val) + : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { SMLoc Start = SMLoc::getFromPointer(Val.begin()); SMLoc End = SMLoc::getFromPointer(Val.end()); SourceRange = SMRange(Start, End); @@ -220,9 +234,10 @@ private: /// Example: /// Section: .text class KeyValueNode : public Node { + virtual void anchor(); public: KeyValueNode(OwningPtr<Document> &D) - : Node(NK_KeyValue, D, StringRef()) + : Node(NK_KeyValue, D, StringRef(), StringRef()) , Key(0) , Value(0) {} @@ -331,6 +346,7 @@ void skip(CollectionType &C) { /// Name: _main /// Scope: Global class MappingNode : public Node { + virtual void anchor(); public: enum MappingType { MT_Block, @@ -338,13 +354,10 @@ public: MT_Inline ///< An inline mapping node is used for "[key: value]". }; - MappingNode(OwningPtr<Document> &D, StringRef Anchor, MappingType MT) - : Node(NK_Mapping, D, Anchor) - , Type(MT) - , IsAtBeginning(true) - , IsAtEnd(false) - , CurrentEntry(0) - {} + MappingNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + MappingType MT) + : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true), + IsAtEnd(false), CurrentEntry(0) {} friend class basic_collection_iterator<MappingNode, KeyValueNode>; typedef basic_collection_iterator<MappingNode, KeyValueNode> iterator; @@ -383,6 +396,7 @@ private: /// - Hello /// - World class SequenceNode : public Node { + virtual void anchor(); public: enum SequenceType { ST_Block, @@ -397,14 +411,12 @@ public: ST_Indentless }; - SequenceNode(OwningPtr<Document> &D, StringRef Anchor, SequenceType ST) - : Node(NK_Sequence, D, Anchor) - , SeqType(ST) - , IsAtBeginning(true) - , IsAtEnd(false) - , WasPreviousTokenFlowEntry(true) // Start with an imaginary ','. - , CurrentEntry(0) - {} + SequenceNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + SequenceType ST) + : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST), IsAtBeginning(true), + IsAtEnd(false), + WasPreviousTokenFlowEntry(true), // Start with an imaginary ','. + CurrentEntry(0) {} friend class basic_collection_iterator<SequenceNode, Node>; typedef basic_collection_iterator<SequenceNode, Node> iterator; @@ -440,9 +452,10 @@ private: /// Example: /// *AnchorName class AliasNode : public Node { + virtual void anchor(); public: AliasNode(OwningPtr<Document> &D, StringRef Val) - : Node(NK_Alias, D, StringRef()), Name(Val) {} + : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} StringRef getName() const { return Name; } Node *getTarget(); @@ -475,6 +488,10 @@ public: return Root = parseBlockNode(); } + const std::map<StringRef, StringRef> &getTagMap() const { + return TagMap; + } + private: friend class Node; friend class document_iterator; @@ -490,18 +507,23 @@ private: /// document. Node *Root; + /// \brief Maps tag prefixes to their expansion. + std::map<StringRef, StringRef> TagMap; + Token &peekNext(); Token getNext(); void setError(const Twine &Message, Token &Location) const; bool failed() const; - void handleTagDirective(const Token &Tag) { - // TODO: Track tags. - } - /// @brief Parse %BLAH directives and return true if any were encountered. bool parseDirectives(); + /// \brief Parse %YAML + void parseYAMLDirective(); + + /// \brief Parse %TAG + void parseTAGDirective(); + /// @brief Consume the next token and error if it is not \a TK. bool expectToken(int TK); }; diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 0f57f44..c19eb23 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" @@ -317,18 +318,20 @@ public: IO(void *Ctxt=NULL); virtual ~IO(); - virtual bool outputting() = 0; + virtual bool outputting() const = 0; virtual unsigned beginSequence() = 0; virtual bool preflightElement(unsigned, void *&) = 0; virtual void postflightElement(void*) = 0; virtual void endSequence() = 0; + virtual bool canElideEmptySequence() = 0; virtual unsigned beginFlowSequence() = 0; virtual bool preflightFlowElement(unsigned, void *&) = 0; virtual void postflightFlowElement(void*) = 0; virtual void endFlowSequence() = 0; + virtual bool mapTag(StringRef Tag, bool Default=false) = 0; virtual void beginMapping() = 0; virtual void endMapping() = 0; virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; @@ -388,7 +391,7 @@ public: typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type mapOptional(const char* Key, T& Val) { // omit key/value instead of outputting empty sequence - if ( this->outputting() && !(Val.begin() != Val.end()) ) + if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) ) return; this->processKey(Key, Val, false); } @@ -403,8 +406,7 @@ public: void mapOptional(const char* Key, T& Val, const T& Default) { this->processKeyWithDefault(Key, Val, Default, false); } - - + private: template <typename T> void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue, @@ -683,18 +685,23 @@ private: /// class Input : public IO { public: - // Construct a yaml Input object from a StringRef and optional user-data. - Input(StringRef InputContent, void *Ctxt=NULL); + // Construct a yaml Input object from a StringRef and optional + // user-data. The DiagHandler can be specified to provide + // alternative error reporting. + Input(StringRef InputContent, + void *Ctxt = NULL, + SourceMgr::DiagHandlerTy DiagHandler = NULL, + void *DiagHandlerCtxt = NULL); ~Input(); - + // Check if there was an syntax or semantic error during parsing. llvm::error_code error(); - // To set alternate error reporting. - void setDiagHandler(llvm::SourceMgr::DiagHandlerTy Handler, void *Ctxt = 0); + static bool classof(const IO *io) { return !io->outputting(); } private: - virtual bool outputting(); + virtual bool outputting() const; + virtual bool mapTag(StringRef, bool); virtual void beginMapping(); virtual void endMapping(); virtual bool preflightKey(const char *, bool, bool, bool &, void *&); @@ -715,8 +722,10 @@ private: virtual void endBitSetScalar(); virtual void scalarString(StringRef &); virtual void setError(const Twine &message); + virtual bool canElideEmptySequence(); class HNode { + virtual void anchor(); public: HNode(Node *n) : _node(n) { } virtual ~HNode() { } @@ -726,9 +735,9 @@ private: }; class EmptyHNode : public HNode { + virtual void anchor(); public: EmptyHNode(Node *n) : HNode(n) { } - virtual ~EmptyHNode() {} static inline bool classof(const HNode *n) { return NullNode::classof(n->_node); } @@ -736,9 +745,9 @@ private: }; class ScalarHNode : public HNode { + virtual void anchor(); public: ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } - virtual ~ScalarHNode() { } StringRef value() const { return _value; } @@ -816,7 +825,10 @@ public: Output(llvm::raw_ostream &, void *Ctxt=NULL); virtual ~Output(); - virtual bool outputting(); + static bool classof(const IO *io) { return io->outputting(); } + + virtual bool outputting() const; + virtual bool mapTag(StringRef, bool); virtual void beginMapping(); virtual void endMapping(); virtual bool preflightKey(const char *key, bool, bool, bool &, void *&); @@ -837,7 +849,7 @@ public: virtual void endBitSetScalar(); virtual void scalarString(StringRef &); virtual void setError(const Twine &message); - + virtual bool canElideEmptySequence(); public: // These are only used by operator<<. They could be private // if that templated operator could be made a friend. @@ -959,8 +971,8 @@ template <typename T> inline typename llvm::enable_if_c<has_SequenceTraits<T>::value,Input &>::type operator>>(Input &yin, T &docSeq) { - yin.setCurrentDocument(); - yamlize(yin, docSeq, true); + if (yin.setCurrentDocument()) + yamlize(yin, docSeq, true); return yin; } diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index e17cddd..50352bd 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -694,7 +694,7 @@ public: }; -/// IntInit - 7 - Represent an initalization by a literal integer value. +/// IntInit - 7 - Represent an initialization by a literal integer value. /// class IntInit : public TypedInit { int64_t Value; diff --git a/include/llvm/TableGen/StringToOffsetTable.h b/include/llvm/TableGen/StringToOffsetTable.h new file mode 100644 index 0000000..d94d3a2 --- /dev/null +++ b/include/llvm/TableGen/StringToOffsetTable.h @@ -0,0 +1,83 @@ +//===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef TBLGEN_STRING_TO_OFFSET_TABLE_H +#define TBLGEN_STRING_TO_OFFSET_TABLE_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/raw_ostream.h" +#include <cctype> + +namespace llvm { + +/// StringToOffsetTable - This class uniques a bunch of nul-terminated strings +/// and keeps track of their offset in a massive contiguous string allocation. +/// It can then output this string blob and use indexes into the string to +/// reference each piece. +class StringToOffsetTable { + StringMap<unsigned> StringOffset; + std::string AggregateString; +public: + + unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) { + StringMapEntry<unsigned> &Entry = StringOffset.GetOrCreateValue(Str, -1U); + if (Entry.getValue() == -1U) { + // Add the string to the aggregate if this is the first time found. + Entry.setValue(AggregateString.size()); + AggregateString.append(Str.begin(), Str.end()); + if (appendZero) + AggregateString += '\0'; + } + + return Entry.getValue(); + } + + void EmitString(raw_ostream &O) { + // Escape the string. + SmallString<256> Str; + raw_svector_ostream(Str).write_escaped(AggregateString); + AggregateString = Str.str(); + + O << " \""; + unsigned CharsPrinted = 0; + for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) { + if (CharsPrinted > 70) { + O << "\"\n \""; + CharsPrinted = 0; + } + O << AggregateString[i]; + ++CharsPrinted; + + // Print escape sequences all together. + if (AggregateString[i] != '\\') + continue; + + assert(i+1 < AggregateString.size() && "Incomplete escape sequence!"); + if (isdigit(AggregateString[i+1])) { + assert(isdigit(AggregateString[i+2]) && + isdigit(AggregateString[i+3]) && + "Expected 3 digit octal escape!"); + O << AggregateString[++i]; + O << AggregateString[++i]; + O << AggregateString[++i]; + CharsPrinted += 3; + } else { + O << AggregateString[++i]; + ++CharsPrinted; + } + } + O << "\""; + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/TableGen/TableGenBackend.h b/include/llvm/TableGen/TableGenBackend.h index bedf7fb..3e4f3cc 100644 --- a/include/llvm/TableGen/TableGenBackend.h +++ b/include/llvm/TableGen/TableGenBackend.h @@ -20,7 +20,7 @@ namespace llvm { class raw_ostream; -/// emitSourceFileHeader - Output a LLVM style file header to the specified +/// emitSourceFileHeader - Output an LLVM style file header to the specified /// raw_ostream. void emitSourceFileHeader(StringRef Desc, raw_ostream &OS); diff --git a/include/llvm/Target/CostTable.h b/include/llvm/Target/CostTable.h index a974b56..34f6041 100644 --- a/include/llvm/Target/CostTable.h +++ b/include/llvm/Target/CostTable.h @@ -25,18 +25,25 @@ struct CostTblEntry { unsigned Cost; }; -/// Find in cost table, TypeTy must be comparable by == -template <class TypeTy> -int CostTableLookup(const CostTblEntry<TypeTy> *Tbl, - unsigned len, int ISD, TypeTy Ty) { +/// Find in cost table, TypeTy must be comparable to CompareTy by == +template <class TypeTy, class CompareTy> +int CostTableLookup(const CostTblEntry<TypeTy> *Tbl, unsigned len, int ISD, + CompareTy Ty) { for (unsigned int i = 0; i < len; ++i) - if (Tbl[i].ISD == ISD && Tbl[i].Type == Ty) + if (ISD == Tbl[i].ISD && Ty == Tbl[i].Type) return i; // Could not find an entry. return -1; } +/// Find in cost table, TypeTy must be comparable to CompareTy by == +template <class TypeTy, class CompareTy, unsigned N> +int CostTableLookup(const CostTblEntry<TypeTy>(&Tbl)[N], int ISD, + CompareTy Ty) { + return CostTableLookup(Tbl, N, ISD, Ty); +} + /// Type Conversion Cost Table template <class TypeTy> struct TypeConversionCostTblEntry { @@ -46,18 +53,28 @@ struct TypeConversionCostTblEntry { unsigned Cost; }; -/// Find in type conversion cost table, TypeTy must be comparable by == -template <class TypeTy> +/// Find in type conversion cost table, TypeTy must be comparable to CompareTy +/// by == +template <class TypeTy, class CompareTy> int ConvertCostTableLookup(const TypeConversionCostTblEntry<TypeTy> *Tbl, - unsigned len, int ISD, TypeTy Dst, TypeTy Src) { + unsigned len, int ISD, CompareTy Dst, + CompareTy Src) { for (unsigned int i = 0; i < len; ++i) - if (Tbl[i].ISD == ISD && Tbl[i].Src == Src && Tbl[i].Dst == Dst) + if (ISD == Tbl[i].ISD && Src == Tbl[i].Src && Dst == Tbl[i].Dst) return i; // Could not find an entry. return -1; } +/// Find in type conversion cost table, TypeTy must be comparable to CompareTy +/// by == +template <class TypeTy, class CompareTy, unsigned N> +int ConvertCostTableLookup(const TypeConversionCostTblEntry<TypeTy>(&Tbl)[N], + int ISD, CompareTy Dst, CompareTy Src) { + return ConvertCostTableLookup(Tbl, N, ISD, Dst, Src); +} + } // namespace llvm diff --git a/include/llvm/Target/Mangler.h b/include/llvm/Target/Mangler.h index e925cd5..eee7bf6 100644 --- a/include/llvm/Target/Mangler.h +++ b/include/llvm/Target/Mangler.h @@ -20,7 +20,6 @@ namespace llvm { class GlobalValue; class MCContext; -class MCSymbol; template <typename T> class SmallVectorImpl; class TargetMachine; class Twine; @@ -34,7 +33,6 @@ public: }; private: - MCContext &Context; const TargetMachine *TM; /// AnonGlobalIDs - We need to give global values the same name every time @@ -48,12 +46,7 @@ private: unsigned NextAnonGlobalID; public: - Mangler(MCContext &Context, const TargetMachine *TM) - : Context(Context), TM(TM), NextAnonGlobalID(1) {} - - /// getSymbol - Return the MCSymbol for the specified global value. This - /// symbol is the main label that is the address of the global. - MCSymbol *getSymbol(const GlobalValue *GV); + Mangler(const TargetMachine *TM) : TM(TM), NextAnonGlobalID(1) {} /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix /// and the specified global variable's name. If the global variable doesn't diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 89ca529..3f6eae6 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -632,6 +632,11 @@ def f64imm : Operand<f64>; /// def zero_reg; +/// All operands which the MC layer classifies as predicates should inherit from +/// this class in some manner. This is already handled for the most commonly +/// used PredicateOperand, but may be useful in other circumstances. +class PredicateOp; + /// OperandWithDefaultOps - This Operand class can be used as the parent class /// for an Operand that needs to be initialized with a default value if /// no value is supplied in a pattern. This class can be used to simplify the @@ -647,7 +652,7 @@ class OperandWithDefaultOps<ValueType ty, dag defaultops> /// AlwaysVal specifies the value of this predicate when set to "always /// execute". class PredicateOperand<ValueType ty, dag OpTypes, dag AlwaysVal> - : OperandWithDefaultOps<ty, AlwaysVal> { + : OperandWithDefaultOps<ty, AlwaysVal>, PredicateOp { let MIOperandInfo = OpTypes; } @@ -795,6 +800,19 @@ def LIFETIME_END : Instruction { let AsmString = "LIFETIME_END"; let neverHasSideEffects = 1; } +def STACKMAP : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id, i32imm:$nbytes, variable_ops); + let isCall = 1; + let mayLoad = 1; +} +def PATCHPOINT : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins i32imm:$id, i32imm:$nbytes, unknown:$callee, + i32imm:$nargs, i32imm:$cc, variable_ops); + let isCall = 1; + let mayLoad = 1; +} } //===----------------------------------------------------------------------===// @@ -1005,6 +1023,17 @@ class SubtargetFeature<string n, string a, string v, string d, list<SubtargetFeature> Implies = i; } +/// Specifies a Subtarget feature that this instruction is deprecated on. +class Deprecated<SubtargetFeature dep> { + SubtargetFeature DeprecatedFeatureMask = dep; +} + +/// A custom predicate used to determine if an instruction is +/// deprecated or not. +class ComplexDeprecationPredicate<string dep> { + string ComplexDeprecationPredicate = dep; +} + //===----------------------------------------------------------------------===// // Processor chip sets - These values represent each of the chip sets supported // by the scheduler. Each Processor definition requires corresponding diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index 1fd0bd9..9cc52a5 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -113,6 +113,7 @@ namespace ISD { struct InputArg { ArgFlagsTy Flags; MVT VT; + EVT ArgVT; bool Used; /// Index original Function's argument. @@ -124,10 +125,11 @@ namespace ISD { unsigned PartOffset; InputArg() : VT(MVT::Other), Used(false) {} - InputArg(ArgFlagsTy flags, EVT vt, bool used, + InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, unsigned partOffs) : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) { VT = vt.getSimpleVT(); + ArgVT = argvt; } }; @@ -138,6 +140,7 @@ namespace ISD { struct OutputArg { ArgFlagsTy Flags; MVT VT; + EVT ArgVT; /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...". bool IsFixed; @@ -151,11 +154,12 @@ namespace ISD { unsigned PartOffset; OutputArg() : IsFixed(false) {} - OutputArg(ArgFlagsTy flags, EVT vt, bool isfixed, + OutputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool isfixed, unsigned origIdx, unsigned partOffs) : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx), PartOffset(partOffs) { VT = vt.getSimpleVT(); + ArgVT = argvt; } }; } diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td index a53ed29..c1bef28 100644 --- a/include/llvm/Target/TargetCallingConv.td +++ b/include/llvm/Target/TargetCallingConv.td @@ -143,4 +143,10 @@ class CallingConv<list<CCAction> actions> { /// returning from getCallPreservedMask(). class CalleeSavedRegs<dag saves> { dag SaveList = saves; + + // Registers that are also preserved across function calls, but should not be + // included in the generated FOO_SaveList array. These registers will be + // included in the FOO_RegMask bit mask. This can be used for registers that + // are saved automatically, like the SPARC register windows. + dag OtherPreserved; } diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index f746daf..d4e14f6 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -181,6 +181,23 @@ public: return false; } + /// Compute the size in bytes and offset within a stack slot of a spilled + /// register or subregister. + /// + /// \param [out] Size in bytes of the spilled value. + /// \param [out] Offset in bytes within the stack slot. + /// \returns true if both Size and Offset are successfully computed. + /// + /// Not all subregisters have computable spill slots. For example, + /// subregisters registers may not be byte-sized, and a pair of discontiguous + /// subregisters has no single offset. + /// + /// Targets with nontrivial bigendian implementations may need to override + /// this, particularly to support spilled vector registers. + virtual bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx, + unsigned &Size, unsigned &Offset, + const TargetMachine *TM) const; + /// reMaterialize - Re-issue the specified 'original' instruction at the /// specific location targeting a new destination register. /// The register in Orig->getOperand(0).getReg() will be substituted by @@ -615,6 +632,8 @@ public: return false; } + virtual bool enableClusterLoads() const { return false; } + virtual bool shouldClusterLoads(MachineInstr *FirstLdSt, MachineInstr *SecondLdSt, unsigned NumLoads) const { @@ -821,6 +840,8 @@ public: const MachineInstr *MI, unsigned *PredCost = 0) const; + virtual unsigned getPredicationCost(const MachineInstr *MI) const; + virtual int getInstrLatency(const InstrItineraryData *ItinData, SDNode *Node) const; @@ -938,6 +959,26 @@ public: return 0; } + /// \brief Return the minimum clearance before an instruction that reads an + /// unused register. + /// + /// For example, AVX instructions may copy part of an register operand into + /// the unused high bits of the destination register. + /// + /// vcvtsi2sdq %rax, %xmm0<undef>, %xmm14 + /// + /// In the code above, vcvtsi2sdq copies %xmm0[127:64] into %xmm14 creating a + /// false dependence on any previous write to %xmm0. + /// + /// This hook works similarly to getPartialRegUpdateClearance, except that it + /// does not take an operand index. Instead sets \p OpNum to the index of the + /// unused register. + virtual unsigned getUndefRegClearance(const MachineInstr *MI, unsigned &OpNum, + const TargetRegisterInfo *TRI) const { + // The default implementation returns 0 for no undef register dependency. + return 0; + } + /// breakPartialRegDependency - Insert a dependency-breaking instruction /// before MI to eliminate an unwanted dependency on OpNum. /// diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h index 8c1f223..46eaef2 100644 --- a/include/llvm/Target/TargetLibraryInfo.h +++ b/include/llvm/Target/TargetLibraryInfo.h @@ -46,6 +46,10 @@ namespace llvm { Znwm, /// void *new(unsigned long, nothrow); ZnwmRKSt9nothrow_t, + /// double __cospi(double x); + cospi, + /// float __cospif(float x); + cospif, /// int __cxa_atexit(void (*f)(void *), void *p, void *d); cxa_atexit, /// void __cxa_guard_abort(guard_t *guard); @@ -61,6 +65,14 @@ namespace llvm { dunder_isoc99_sscanf, /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); memcpy_chk, + /// double __sincospi_stret(double x); + sincospi_stret, + /// float __sincospi_stretf(float x); + sincospi_stretf, + /// double __sinpi(double x); + sinpi, + /// float __sinpif(float x); + sinpif, /// double __sqrt_finite(double x); sqrt_finite, /// float __sqrt_finite(float x); @@ -695,10 +707,13 @@ public: case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: + case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: - case LibFunc::memcmp: + case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: + case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: + case LibFunc::memchr: return true; } return false; diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index c3fa3cc..5ab04f7 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -148,10 +148,13 @@ public: bool isBigEndian() const { return !IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; } - // Return the pointer type for the given address space, defaults to - // the pointer type from the data layout. - // FIXME: The default needs to be removed once all the code is updated. - virtual MVT getPointerTy(uint32_t /*AS*/ = 0) const { return PointerTy; } + + /// Return the pointer type for the given address space, defaults to + /// the pointer type from the data layout. + /// FIXME: The default needs to be removed once all the code is updated. + virtual MVT getPointerTy(uint32_t /*AS*/ = 0) const; + unsigned getPointerSizeInBits(uint32_t AS = 0) const; + unsigned getPointerTypeSizeInBits(Type *Ty) const; virtual MVT getScalarShiftAmountTy(EVT LHSTy) const; EVT getShiftAmountTy(EVT LHSTy) const; @@ -201,6 +204,17 @@ public: return PredictableSelectIsExpensive; } + /// isLoadBitCastBeneficial() - Return true if the following transform + /// is beneficial. + /// fold (conv (load x)) -> (load (conv*)x) + /// On architectures that don't natively support some vector loads efficiently, + /// casting the load to a smaller vector of larger types and loading + /// is more efficient, however, this can be undone by optimizations in + /// dag combiner. + virtual bool isLoadBitCastBeneficial(EVT /* Load */, EVT /* Bitcast */) const { + return true; + } + /// Return the ValueType of the result of SETCC operations. Also used to /// obtain the target's preferred type for the condition operand of SELECT and /// BRCOND nodes. In the case of BRCOND the argument passed is MVT::Other @@ -518,13 +532,12 @@ public: LegalizeAction getCondCodeAction(ISD::CondCode CC, MVT VT) const { assert((unsigned)CC < array_lengthof(CondCodeActions) && - (unsigned)VT.SimpleTy < sizeof(CondCodeActions[0])*4 && + ((unsigned)VT.SimpleTy >> 4) < array_lengthof(CondCodeActions[0]) && "Table isn't big enough!"); - /// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 64bit - /// value and the upper 27 bits index into the second dimension of the - /// array to select what 64bit value to use. - LegalizeAction Action = (LegalizeAction) - ((CondCodeActions[CC][VT.SimpleTy >> 5] >> (2*(VT.SimpleTy & 0x1F))) & 3); + // See setCondCodeAction for how this is encoded. + uint32_t Shift = 2 * (VT.SimpleTy & 0xF); + uint32_t Value = CondCodeActions[CC][VT.SimpleTy >> 4]; + LegalizeAction Action = (LegalizeAction) ((Value >> Shift) & 0x3); assert(Action != Promote && "Can't promote condition code!"); return Action; } @@ -568,14 +581,18 @@ public: /// otherwise it will assert. EVT getValueType(Type *Ty, bool AllowUnknown = false) const { // Lower scalar pointers to native pointer types. - if (Ty->isPointerTy()) return PointerTy; + if (PointerType *PTy = dyn_cast<PointerType>(Ty)) + return getPointerTy(PTy->getAddressSpace()); if (Ty->isVectorTy()) { VectorType *VTy = cast<VectorType>(Ty); Type *Elm = VTy->getElementType(); // Lower vectors of pointers to native pointer types. - if (Elm->isPointerTy()) - Elm = EVT(PointerTy).getTypeForEVT(Ty->getContext()); + if (PointerType *PT = dyn_cast<PointerType>(Elm)) { + EVT PointerTy(getPointerTy(PT->getAddressSpace())); + Elm = PointerTy.getTypeForEVT(Ty->getContext()); + } + return EVT::getVectorVT(Ty->getContext(), EVT::getEVT(Elm, false), VTy->getNumElements()); } @@ -821,6 +838,11 @@ public: return 0; } + /// Returns true if a cast between SrcAS and DestAS is a noop. + virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { + return false; + } + //===--------------------------------------------------------------------===// /// \name Helpers for TargetTransformInfo implementations /// @{ @@ -1014,13 +1036,12 @@ protected: assert(VT < MVT::LAST_VALUETYPE && (unsigned)CC < array_lengthof(CondCodeActions) && "Table isn't big enough!"); - /// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 64bit - /// value and the upper 27 bits index into the second dimension of the - /// array to select what 64bit value to use. - CondCodeActions[(unsigned)CC][VT.SimpleTy >> 5] - &= ~(uint64_t(3UL) << (VT.SimpleTy & 0x1F)*2); - CondCodeActions[(unsigned)CC][VT.SimpleTy >> 5] - |= (uint64_t)Action << (VT.SimpleTy & 0x1F)*2; + /// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 32-bit + /// value and the upper 27 bits index into the second dimension of the array + /// to select what 32-bit value to use. + uint32_t Shift = 2 * (VT.SimpleTy & 0xF); + CondCodeActions[CC][VT.SimpleTy >> 4] &= ~((uint32_t)0x3 << Shift); + CondCodeActions[CC][VT.SimpleTy >> 4] |= (uint32_t)Action << Shift; } /// If Opc/OrigVT is specified as being promoted, the promotion code defaults @@ -1181,6 +1202,37 @@ public: return false; } + /// Return true if the target supplies and combines to a paired load + /// two loaded values of type LoadedType next to each other in memory. + /// RequiredAlignment gives the minimal alignment constraints that must be met + /// to be able to select this paired load. + /// + /// This information is *not* used to generate actual paired loads, but it is + /// used to generate a sequence of loads that is easier to combine into a + /// paired load. + /// For instance, something like this: + /// a = load i64* addr + /// b = trunc i64 a to i32 + /// c = lshr i64 a, 32 + /// d = trunc i64 c to i32 + /// will be optimized into: + /// b = load i32* addr1 + /// d = load i32* addr2 + /// Where addr1 = addr2 +/- sizeof(i32). + /// + /// In other words, unless the target performs a post-isel load combining, + /// this information should not be provided because it will generate more + /// loads. + virtual bool hasPairedLoad(Type * /*LoadedType*/, + unsigned & /*RequiredAligment*/) const { + return false; + } + + virtual bool hasPairedLoad(EVT /*LoadedType*/, + unsigned & /*RequiredAligment*/) const { + return false; + } + /// Return true if zero-extending the specific node Val to type VT2 is free /// (either because it's implicitly zero-extended such as ARM ldrb / ldrh or /// because it's folded such as X86 zero-extending loads). @@ -1262,10 +1314,6 @@ private: const DataLayout *TD; const TargetLoweringObjectFile &TLOF; - /// The type to use for pointers for the default address space, usually i32 or - /// i64. - MVT PointerTy; - /// True if this is a little endian target. bool IsLittleEndian; @@ -1414,9 +1462,9 @@ private: /// indicates how instruction selection should deal with the condition code. /// /// Because each CC action takes up 2 bits, we need to have the array size be - /// large enough to fit all of the value types. This can be done by dividing - /// the MVT::LAST_VALUETYPE by 32 and adding one. - uint64_t CondCodeActions[ISD::SETCC_INVALID][(MVT::LAST_VALUETYPE / 32) + 1]; + /// large enough to fit all of the value types. This can be done by rounding + /// up the MVT::LAST_VALUETYPE value to the next multiple of 16. + uint32_t CondCodeActions[ISD::SETCC_INVALID][(MVT::LAST_VALUETYPE + 15) / 16]; ValueTypeActionImpl ValueTypeActions; @@ -1471,10 +1519,12 @@ public: if (NumElts == 1) return LegalizeKind(TypeScalarizeVector, EltVT); - // Try to widen vector elements until a legal type is found. + // Try to widen vector elements until the element type is a power of two and + // promote it to a legal type later on, for example: + // <3 x i8> -> <4 x i8> -> <4 x i32> if (EltVT.isInteger()) { // Vectors with a number of elements that is not a power of two are always - // widened, for example <3 x float> -> <4 x float>. + // widened, for example <3 x i8> -> <4 x i8>. if (!VT.isPow2VectorType()) { NumElts = (unsigned)NextPowerOf2(NumElts); EVT NVT = EVT::getVectorVT(Context, EltVT, NumElts); @@ -1503,7 +1553,8 @@ public: // Stop trying when getting a non-simple element type. // Note that vector elements may be greater than legal vector element - // types. Example: X86 XMM registers hold 64bit element on 32bit systems. + // types. Example: X86 XMM registers hold 64bit element on 32bit + // systems. if (!EltVT.isSimple()) break; // Build a new vector type and check if it is legal. @@ -1664,7 +1715,8 @@ public: /// by reference if this node can be combined with a load / store to form a /// post-indexed load / store. virtual bool getPostIndexedAddressParts(SDNode * /*N*/, SDNode * /*Op*/, - SDValue &/*Base*/, SDValue &/*Offset*/, + SDValue &/*Base*/, + SDValue &/*Offset*/, ISD::MemIndexedMode &/*AM*/, SelectionDAG &/*DAG*/) const { return false; @@ -1702,9 +1754,12 @@ public: SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, SDLoc DL) const; - SDValue makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, - const SDValue *Ops, unsigned NumOps, - bool isSigned, SDLoc dl) const; + /// Returns a pair of (return value, chain). + std::pair<SDValue, SDValue> makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, + EVT RetVT, const SDValue *Ops, + unsigned NumOps, bool isSigned, + SDLoc dl, bool doesNotReturn = false, + bool isReturnValueUsed = true) const; //===--------------------------------------------------------------------===// // TargetLowering Optimization Methods @@ -1882,6 +1937,8 @@ public: ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), isSRet(false), isNest(false), isByVal(false), isReturned(false), Alignment(0) { } + + void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); }; typedef std::vector<ArgListEntry> ArgListTy; @@ -2015,6 +2072,12 @@ public: return VT.bitsLT(MinVT) ? MinVT : VT; } + /// Returns a 0 terminated array of registers that can be safely used as + /// scratch registers. + virtual const uint16_t *getScratchRegisters(CallingConv::ID CC) const { + return NULL; + } + /// This callback is invoked by the type legalizer to legalize nodes with an /// illegal operand type but legal result types. It replaces the /// LowerOperation callback in the type Legalizer. The reason we can not do @@ -2211,12 +2274,12 @@ public: // Instruction Emitting Hooks // - // This method should be implemented by targets that mark instructions with - // the 'usesCustomInserter' flag. These instructions are special in various - // ways, which require special support to insert. The specified MachineInstr - // is created but not inserted into any basic blocks, and this method is - // called to expand it into a sequence of instructions, potentially also - // creating new basic blocks and control flow. + /// This method should be implemented by targets that mark instructions with + /// the 'usesCustomInserter' flag. These instructions are special in various + /// ways, which require special support to insert. The specified MachineInstr + /// is created but not inserted into any basic blocks, and this method is + /// called to expand it into a sequence of instructions, potentially also + /// creating new basic blocks and control flow. virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 7f15b74..284b6bb 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -117,6 +117,10 @@ public: MachineModuleInfo *MMI, unsigned Encoding, MCStreamer &Streamer) const; + /// Return the MCSymbol for the specified global value. This symbol is the + /// main label that is the address of the global + MCSymbol *getSymbol(Mangler &M, const GlobalValue *GV) const; + // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. virtual MCSymbol * getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index fd7228a..11b0f5f 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -29,7 +29,6 @@ class GlobalValue; class MCAsmInfo; class MCCodeGenInfo; class MCContext; -class PassManagerBase; class Target; class DataLayout; class TargetLibraryInfo; @@ -47,6 +46,12 @@ class VectorTargetTransformInfo; class formatted_raw_ostream; class raw_ostream; +// The old pass manager infrastructure is hidden in a legacy namespace now. +namespace legacy { +class PassManagerBase; +} +using legacy::PassManagerBase; + //===----------------------------------------------------------------------===// /// /// TargetMachine - Primary interface to the complete machine description for @@ -70,7 +75,8 @@ protected: // Can only create subclasses. std::string TargetFS; /// CodeGenInfo - Low level target information such as relocation model. - const MCCodeGenInfo *CodeGenInfo; + /// Non-const to allow resetting optimization level per-function. + MCCodeGenInfo *CodeGenInfo; /// AsmInfo - Contains target specific asm information. /// @@ -208,6 +214,9 @@ public: /// Default, or Aggressive. CodeGenOpt::Level getOptLevel() const; + /// \brief Overrides the optimization level. + void setOptLevel(CodeGenOpt::Level Level) const; + void setFastISel(bool Enable) { Options.EnableFastISel = Enable; } bool shouldPrintMachineCode() const { return Options.PrintMachineCode; } diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h index 516e070..bd74cb9 100644 --- a/include/llvm/Target/TargetOpcodes.h +++ b/include/llvm/Target/TargetOpcodes.h @@ -69,8 +69,9 @@ namespace TargetOpcode { DBG_VALUE = 11, /// REG_SEQUENCE - This variadic instruction is used to form a register that - /// represent a consecutive sequence of sub-registers. It's used as register - /// coalescing / allocation aid and must be eliminated before code emission. + /// represents a consecutive sequence of sub-registers. It's used as a + /// register coalescing / allocation aid and must be eliminated before code + /// emission. // In SDNode form, the first operand encodes the register class created by // the REG_SEQUENCE, while each subsequent pair names a vreg + subreg index // pair. Once it has been lowered to a MachineInstr, the regclass operand @@ -91,7 +92,19 @@ namespace TargetOpcode { /// Lifetime markers. LIFETIME_START = 15, - LIFETIME_END = 16 + LIFETIME_END = 16, + + /// A Stackmap instruction captures the location of live variables at its + /// position in the instruction stream. It is followed by a shadow of bytes + /// that must lie within the function and not contain another stackmap. + STACKMAP = 17, + + /// Patchable call instruction - this instruction represents a call to a + /// constant address, followed by a series of NOPs. It is intended to + /// support optimizations for dynamic languages (such as javascript) that + /// rewrite calls to runtimes with more efficient code sequences. + /// This also implies a stack map. + PATCHPOINT = 18 }; } // end namespace TargetOpcode } // end namespace llvm diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 82fccde..958bea6 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -901,6 +901,7 @@ static inline raw_ostream &operator<<(raw_ostream &OS, const PrintReg &PR) { /// Usage: OS << PrintRegUnit(Unit, TRI) << '\n'; /// class PrintRegUnit { +protected: const TargetRegisterInfo *TRI; unsigned Unit; public: @@ -914,6 +915,21 @@ static inline raw_ostream &operator<<(raw_ostream &OS, const PrintRegUnit &PR) { return OS; } +/// PrintVRegOrUnit - It is often convenient to track virtual registers and +/// physical register units in the same list. +class PrintVRegOrUnit : protected PrintRegUnit { +public: + PrintVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *tri) + : PrintRegUnit(VRegOrUnit, tri) {} + void print(raw_ostream&) const; +}; + +static inline raw_ostream &operator<<(raw_ostream &OS, + const PrintVRegOrUnit &PR) { + PR.print(OS); + return OS; +} + } // End llvm namespace #endif diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 575cb83..9d4858a 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -76,7 +76,7 @@ def instregex; // See MCSchedule.h for detailed comments. class SchedMachineModel { int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle. - int MinLatency = -1; // Determines which instrucions are allowed in a group. + int MinLatency = -1; // Determines which instructions are allowed in a group. // (-1) inorder (0) ooo, (1): inorder +var latencies. int MicroOpBufferSize = -1; // Max micro-ops that can be buffered. int LoadLatency = -1; // Cycles for loads to access the cache. @@ -86,6 +86,15 @@ class SchedMachineModel { // Per-cycle resources tables. ProcessorItineraries Itineraries = NoItineraries; + // Subtargets that define a model for only a subset of instructions + // that have a scheduling class (itinerary class or SchedRW list) + // and may actually be generated for that subtarget must clear this + // bit. Otherwise, the scheduler considers an unmodelled opcode to + // be an error. This should only be set during initial bringup, + // or there will be no way to catch simple errors in the model + // resulting from changes to the instruction definitions. + bit CompleteModel = 1; + bit NoModel = 0; // Special tag to indicate missing machine model. } diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index befab43..d94bdc6 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -383,6 +383,7 @@ def ftrunc : SDNode<"ISD::FTRUNC" , SDTFPUnaryOp>; def fceil : SDNode<"ISD::FCEIL" , SDTFPUnaryOp>; def ffloor : SDNode<"ISD::FFLOOR" , SDTFPUnaryOp>; def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; +def frnd : SDNode<"ISD::FROUND" , SDTFPUnaryOp>; def fround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; def fextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; @@ -464,6 +465,8 @@ def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTypeProfile<1, 2, [SDTCisPtrTy<2>]>, []>; def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; +def concat_vectors : SDNode<"ISD::CONCAT_VECTORS", + SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1, 2>]>,[]>; // This operator does not do subvector type checking. The ARM // backend, at least, needs it. diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index fe2fba4..3474ee4 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -94,6 +94,74 @@ public: MachinePointerInfo DstPtrInfo) const { return SDValue(); } + + /// EmitTargetCodeForMemcmp - Emit target-specific code that performs a + /// memcmp, in cases where that is faster than a libcall. The first + /// returned SDValue is the result of the memcmp and the second is + /// the chain. Both SDValues can be null if a normal libcall should + /// be used. + virtual std::pair<SDValue, SDValue> + EmitTargetCodeForMemcmp(SelectionDAG &DAG, SDLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, MachinePointerInfo Op1PtrInfo, + MachinePointerInfo Op2PtrInfo) const { + return std::make_pair(SDValue(), SDValue()); + } + + /// EmitTargetCodeForMemchr - Emit target-specific code that performs a + /// memchr, in cases where that is faster than a libcall. The first + /// returned SDValue is the result of the memchr and the second is + /// the chain. Both SDValues can be null if a normal libcall should + /// be used. + virtual std::pair<SDValue, SDValue> + EmitTargetCodeForMemchr(SelectionDAG &DAG, SDLoc dl, SDValue Chain, + SDValue Src, SDValue Char, SDValue Length, + MachinePointerInfo SrcPtrInfo) const { + return std::make_pair(SDValue(), SDValue()); + } + + /// EmitTargetCodeForStrcpy - Emit target-specific code that performs a + /// strcpy or stpcpy, in cases where that is faster than a libcall. + /// The first returned SDValue is the result of the copy (the start + /// of the destination string for strcpy, a pointer to the null terminator + /// for stpcpy) and the second is the chain. Both SDValues can be null + /// if a normal libcall should be used. + virtual std::pair<SDValue, SDValue> + EmitTargetCodeForStrcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain, + SDValue Dest, SDValue Src, + MachinePointerInfo DestPtrInfo, + MachinePointerInfo SrcPtrInfo, + bool isStpcpy) const { + return std::make_pair(SDValue(), SDValue()); + } + + /// EmitTargetCodeForStrcmp - Emit target-specific code that performs a + /// strcmp, in cases where that is faster than a libcall. The first + /// returned SDValue is the result of the strcmp and the second is + /// the chain. Both SDValues can be null if a normal libcall should + /// be used. + virtual std::pair<SDValue, SDValue> + EmitTargetCodeForStrcmp(SelectionDAG &DAG, SDLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + MachinePointerInfo Op1PtrInfo, + MachinePointerInfo Op2PtrInfo) const { + return std::make_pair(SDValue(), SDValue()); + } + + virtual std::pair<SDValue, SDValue> + EmitTargetCodeForStrlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain, + SDValue Src, MachinePointerInfo SrcPtrInfo) const { + return std::make_pair(SDValue(), SDValue()); + } + + virtual std::pair<SDValue, SDValue> + EmitTargetCodeForStrnlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain, + SDValue Src, SDValue MaxLength, + MachinePointerInfo SrcPtrInfo) const { + return std::make_pair(SDValue(), SDValue()); + } }; } // end llvm namespace diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index b2d405d..1b2e06a 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -25,6 +25,7 @@ class SDep; class SUnit; class TargetRegisterClass; class TargetSchedModel; +struct MachineSchedPolicy; template <typename T> class SmallVectorImpl; //===----------------------------------------------------------------------===// @@ -55,6 +56,9 @@ public: return 0; } + /// \brief Temporary API to test migration to MI scheduler. + bool useMachineScheduler() const; + /// \brief True if the subtarget should run MachineScheduler after aggressive /// coalescing. /// @@ -62,6 +66,16 @@ public: /// scheduler. It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; + /// \brief Override generic scheduling policy within a region. + /// + /// This is a convenient way for targets that don't provide any custom + /// scheduling heuristics (no custom MachineSchedStrategy) to make + /// changes to the generic scheduling policy. + virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, + MachineInstr *begin, + MachineInstr *end, + unsigned NumRegionInstrs) const {} + // enablePostRAScheduler - If the target can benefit from post-regalloc // scheduling and the specified optimization level meets the requirement // return true to enable post-register-allocation scheduling. In @@ -75,6 +89,10 @@ public: virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep& dep) const { } + /// \brief Enable use of alias analysis during code generation (during MI + /// scheduling, DAGCombine, etc.). + virtual bool useAA() const; + /// \brief Reset the features for the subtarget. virtual void resetSubtargetFeatures(const MachineFunction *MF) { } }; diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index e6eb8d3..7f51c51 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -104,12 +104,16 @@ Pass *createPruneEHPass(); //===----------------------------------------------------------------------===// /// createInternalizePass - This pass loops over all of the functions in the -/// input module, internalizing all globals (functions and variables) not in the -/// given exportList. +/// input module, internalizing all globals (functions and variables) it can. +//// +/// The symbols in \p ExportList are never internalized. +/// +/// The symbol in DSOList are internalized if it is safe to drop them from +/// the symbol table. /// /// Note that commandline options that are used with the above function are not /// used now! -ModulePass *createInternalizePass(ArrayRef<const char *> exportList); +ModulePass *createInternalizePass(ArrayRef<const char *> ExportList); /// createInternalizePass - Same as above, but with an empty exportList. ModulePass *createInternalizePass(); diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 75631b3..2788774 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -18,10 +18,16 @@ #include <vector> namespace llvm { - class TargetLibraryInfo; - class PassManagerBase; - class Pass; - class FunctionPassManager; +class TargetLibraryInfo; +class Pass; + +// The old pass manager infrastructure is hidden in a legacy namespace now. +namespace legacy { +class PassManagerBase; +class FunctionPassManager; +} +using legacy::PassManagerBase; +using legacy::FunctionPassManager; /// PassManagerBuilder - This class is used to set up a standard optimization /// sequence for languages like C and C++, allowing some APIs to customize the @@ -106,6 +112,7 @@ public: bool SLPVectorize; bool LoopVectorize; bool LateVectorize; + bool RerollLoops; private: /// ExtensionList - This is list of all of the extensions that are registered. diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index d1b6fe1..8a1b34e 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -16,20 +16,25 @@ #include "llvm/ADT/StringRef.h" +#if defined(__GNUC__) && defined(__linux__) +inline void *getDFSanArgTLSPtrForJIT() { + extern __thread __attribute__((tls_model("initial-exec"))) + void *__dfsan_arg_tls; + return (void *)&__dfsan_arg_tls; +} + +inline void *getDFSanRetValTLSPtrForJIT() { + extern __thread __attribute__((tls_model("initial-exec"))) + void *__dfsan_retval_tls; + return (void *)&__dfsan_retval_tls; +} +#endif + namespace llvm { class ModulePass; class FunctionPass; -// Insert edge profiling instrumentation -ModulePass *createEdgeProfilerPass(); - -// Insert optimal edge profiling instrumentation -ModulePass *createOptimalEdgeProfilerPass(); - -// Insert path profiling instrumentation -ModulePass *createPathProfilerPass(); - // Insert GCOV profiling instrumentation struct GCOVOptions { static GCOVOptions getDefault(); @@ -74,6 +79,19 @@ FunctionPass *createMemorySanitizerPass(bool TrackOrigins = false, // Insert ThreadSanitizer (race detection) instrumentation FunctionPass *createThreadSanitizerPass(StringRef BlacklistFile = StringRef()); +// Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation +ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(), + void *(*getArgTLS)() = 0, + void *(*getRetValTLS)() = 0); + +#if defined(__GNUC__) && defined(__linux__) +inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile = + StringRef()) { + return createDataFlowSanitizerPass(ABIListFile, getDFSanArgTLSPtrForJIT, + getDFSanRetValTLSPtrForJIT); +} +#endif + // BoundsChecking - This pass instruments the code to perform run-time bounds // checking on loads, stores, and other memory intrinsics. FunctionPass *createBoundsCheckingPass(); diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 037ab6b..1521c4c 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -15,6 +15,8 @@ #ifndef LLVM_TRANSFORMS_SCALAR_H #define LLVM_TRANSFORMS_SCALAR_H +#include "llvm/ADT/StringRef.h" + namespace llvm { class FunctionPass; @@ -138,7 +140,14 @@ Pass *createLoopInstSimplifyPass(); // // LoopUnroll - This pass is a simple loop unrolling pass. // -Pass *createLoopUnrollPass(int Threshold = -1, int Count = -1, int AllowPartial = -1); +Pass *createLoopUnrollPass(int Threshold = -1, int Count = -1, + int AllowPartial = -1, int Runtime = -1); + +//===----------------------------------------------------------------------===// +// +// LoopReroll - This pass is a simple loop rerolling pass. +// +Pass *createLoopRerollPass(); //===----------------------------------------------------------------------===// // @@ -267,13 +276,6 @@ extern char &LowerInvokePassID; //===----------------------------------------------------------------------===// // -// BlockPlacement - This pass reorders basic blocks in order to increase the -// number of fall-through conditional branches. -// -FunctionPass *createBlockPlacementPass(); - -//===----------------------------------------------------------------------===// -// // LCSSA - This pass inserts phi nodes at loop boundaries to simplify other loop // optimizations. // @@ -354,6 +356,20 @@ extern char &InstructionSimplifierID; FunctionPass *createLowerExpectIntrinsicPass(); +//===----------------------------------------------------------------------===// +// +// PartiallyInlineLibCalls - Tries to inline the fast path of library +// calls such as sqrt. +// +FunctionPass *createPartiallyInlineLibCallsPass(); + +//===----------------------------------------------------------------------===// +// +// SampleProfilePass - Loads sample profile data from disk and generates +// IR metadata to reflect the profile. +FunctionPass *createSampleProfileLoaderPass(); +FunctionPass *createSampleProfileLoaderPass(StringRef Name); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/GlobalStatus.h b/include/llvm/Transforms/Utils/GlobalStatus.h new file mode 100644 index 0000000..c366095 --- /dev/null +++ b/include/llvm/Transforms/Utils/GlobalStatus.h @@ -0,0 +1,82 @@ +//===- GlobalStatus.h - Compute status info for globals ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_GLOBALSTATUS_H +#define LLVM_TRANSFORMS_UTILS_GLOBALSTATUS_H + +#include "llvm/IR/Instructions.h" + +namespace llvm { +class Value; +class Function; + +/// It is safe to destroy a constant iff it is only used by constants itself. +/// Note that constants cannot be cyclic, so this test is pretty easy to +/// implement recursively. +/// +bool isSafeToDestroyConstant(const Constant *C); + +/// As we analyze each global, keep track of some information about it. If we +/// find out that the address of the global is taken, none of this info will be +/// accurate. +struct GlobalStatus { + /// True if the global's address is used in a comparison. + bool IsCompared; + + /// True if the global is ever loaded. If the global isn't ever loaded it + /// can be deleted. + bool IsLoaded; + + /// Keep track of what stores to the global look like. + enum StoredType { + /// There is no store to this global. It can thus be marked constant. + NotStored, + + /// This global is stored to, but the only thing stored is the constant it + /// was initialized with. This is only tracked for scalar globals. + InitializerStored, + + /// This global is stored to, but only its initializer and one other value + /// is ever stored to it. If this global isStoredOnce, we track the value + /// stored to it in StoredOnceValue below. This is only tracked for scalar + /// globals. + StoredOnce, + + /// This global is stored to by multiple values or something else that we + /// cannot track. + Stored + } StoredType; + + /// If only one value (besides the initializer constant) is ever stored to + /// this global, keep track of what value it is. + Value *StoredOnceValue; + + /// These start out null/false. When the first accessing function is noticed, + /// it is recorded. When a second different accessing function is noticed, + /// HasMultipleAccessingFunctions is set to true. + const Function *AccessingFunction; + bool HasMultipleAccessingFunctions; + + /// Set to true if this global has a user that is not an instruction (e.g. a + /// constant expr or GV initializer). + bool HasNonInstructionUser; + + /// Set to the strongest atomic ordering requirement. + AtomicOrdering Ordering; + + /// Look at all uses of the global and fill in the GlobalStatus structure. If + /// the global has its address taken, return true to indicate we can't do + /// anything with it. + static bool analyzeGlobal(const Value *V, GlobalStatus &GS); + + GlobalStatus(); +}; +} + +#endif diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 65755d0..5586c15 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -203,12 +203,17 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP, ++i, ++GTI) { Value *Op = *i; uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; - if (ConstantInt *OpC = dyn_cast<ConstantInt>(Op)) { - if (OpC->isZero()) continue; + if (Constant *OpC = dyn_cast<Constant>(Op)) { + if (OpC->isZeroValue()) + continue; // Handle a struct index, which adds its field offset to the pointer. if (StructType *STy = dyn_cast<StructType>(*GTI)) { - Size = TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); + if (OpC->getType()->isVectorTy()) + OpC = OpC->getSplatValue(); + + uint64_t OpValue = cast<ConstantInt>(OpC)->getZExtValue(); + Size = TD.getStructLayout(STy)->getElementOffset(OpValue); if (Size) Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size), diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index 2f28f33..22f46e5 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -20,7 +20,6 @@ namespace llvm { class AllocaInst; -class DataLayout; class DominatorTree; class AliasSetTracker; @@ -30,7 +29,7 @@ class AliasSetTracker; /// (transitively) using this alloca. This also enforces that there is only /// ever one layer of bitcasts or GEPs between the alloca and the lifetime /// markers. -bool isAllocaPromotable(const AllocaInst *AI, const DataLayout *DL); +bool isAllocaPromotable(const AllocaInst *AI); /// \brief Promote the specified list of alloca instructions into scalar /// registers, inserting PHI nodes as appropriate. @@ -42,7 +41,7 @@ bool isAllocaPromotable(const AllocaInst *AI, const DataLayout *DL); /// If AST is specified, the specified tracker is updated to reflect changes /// made to the IR. void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT, - const DataLayout *DL, AliasSetTracker *AST = 0); + AliasSetTracker *AST = 0); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/SpecialCaseList.h b/include/llvm/Transforms/Utils/SpecialCaseList.h index 787ddb0..34c28fc 100644 --- a/include/llvm/Transforms/Utils/SpecialCaseList.h +++ b/include/llvm/Transforms/Utils/SpecialCaseList.h @@ -49,6 +49,7 @@ namespace llvm { class Function; +class GlobalAlias; class GlobalVariable; class MemoryBuffer; class Module; @@ -57,8 +58,17 @@ class StringRef; class SpecialCaseList { public: - SpecialCaseList(const StringRef Path); - SpecialCaseList(const MemoryBuffer *MB); + /// Parses the special case list from a file. If Path is empty, returns + /// an empty special case list. On failure, returns 0 and writes an error + /// message to string. + static SpecialCaseList *create(const StringRef Path, std::string &Error); + /// Parses the special case list from a memory buffer. On failure, returns + /// 0 and writes an error message to string. + static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error); + /// Parses the special case list from a file. On failure, reports a fatal + /// error. + static SpecialCaseList *createOrDie(const StringRef Path); + ~SpecialCaseList(); /// Returns whether either this function or its source file are listed in the @@ -70,31 +80,29 @@ class SpecialCaseList { bool isIn(const GlobalVariable &G, const StringRef Category = StringRef()) const; + /// Returns whether this global alias is listed in the given category, which + /// may be omitted to search the empty category. + /// + /// If GA aliases a function, the alias's name is matched as a function name + /// would be. Similarly, aliases of globals are matched like globals. + bool isIn(const GlobalAlias &GA, + const StringRef Category = StringRef()) const; + /// Returns whether this module is listed in the given category, which may be /// omitted to search the empty category. bool isIn(const Module &M, const StringRef Category = StringRef()) const; - /// Returns whether either this function or its source file are listed in any - /// category. Category will contain the name of an arbitrary category in - /// which this function is listed. - bool findCategory(const Function &F, StringRef &Category) const; - - /// Returns whether this global, its type or its source file are listed in any - /// category. Category will contain the name of an arbitrary category in - /// which this global is listed. - bool findCategory(const GlobalVariable &G, StringRef &Category) const; - - /// Returns whether this module is listed in any category. Category will - /// contain the name of an arbitrary category in which this module is listed. - bool findCategory(const Module &M, StringRef &Category) const; - private: + SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + struct Entry; StringMap<StringMap<Entry> > Entries; - void init(const MemoryBuffer *MB); - bool findCategory(const StringRef Section, const StringRef Query, - StringRef &Category) const; + SpecialCaseList(); + /// Parses just-constructed SpecialCaseList entries from a memory buffer. + bool parse(const MemoryBuffer *MB, std::string &Error); + bool inSectionCategory(const StringRef Section, const StringRef Query, const StringRef Category) const; }; diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index 54506cf..933c85c 100644 --- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -34,7 +34,7 @@ public: // We can preserve non-critical-edgeness when we unify function exit nodes virtual void getAnalysisUsage(AnalysisUsage &AU) const; - // getReturn|Unwind|UnreachableBlock - Return the new single (or nonexistant) + // getReturn|Unwind|UnreachableBlock - Return the new single (or nonexistent) // return, unwind, or unreachable basic blocks in the CFG. // BasicBlock *getReturnBlock() const { return ReturnBlock; } diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h index 8d0db16..823c5fb 100644 --- a/include/llvm/Transforms/Vectorize.h +++ b/include/llvm/Transforms/Vectorize.h @@ -114,7 +114,7 @@ createBBVectorizePass(const VectorizeConfig &C = VectorizeConfig()); // // LoopVectorize - Create a loop vectorization pass. // -Pass *createLoopVectorizePass(); +Pass *createLoopVectorizePass(bool NoUnrolling = false); //===----------------------------------------------------------------------===// // |