diff options
Diffstat (limited to 'include')
398 files changed, 15289 insertions, 7181 deletions
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 6587e77..f2fe764 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -21,8 +21,8 @@ /* Need these includes to support the LLVM 'cast' template for the C++ 'wrap' and 'unwrap' conversion functions. */ -#include "llvm/IRBuilder.h" -#include "llvm/Module.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" #include "llvm/PassRegistry.h" extern "C" { @@ -1803,7 +1803,7 @@ LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg); * Set the alignment for a function parameter. * * @see llvm::Argument::addAttr() - * @see llvm::Attribute::constructAlignmentFromInt() + * @see llvm::AttrBuilder::addAlignmentAttr() */ void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align); @@ -1869,6 +1869,27 @@ LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count); const char *LLVMGetMDString(LLVMValueRef V, unsigned* Len); /** + * Obtain the number of operands from an MDNode value. + * + * @param V MDNode to get number of operands from. + * @return Number of operands of the MDNode. + */ +unsigned LLVMGetMDNodeNumOperands(LLVMValueRef V); + +/** + * Obtain the given MDNode's operands. + * + * The passed LLVMValueRef pointer should point to enough memory to hold all of + * the operands of the given MDNode (see LLVMGetMDNodeNumOperands) as + * LLVMValueRefs. This memory will be populated with the LLVMValueRefs of the + * MDNode's operands. + * + * @param V MDNode to get the operands from. + * @param Dest Destination array for operands. + */ +void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest); + +/** * @} */ diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index 69fdc64..df65a7b 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -139,13 +139,39 @@ extern "C" { * by passing a block of information in the DisInfo parameter and specifying the * TagType and callback functions as described above. These can all be passed * as NULL. If successful, this returns a disassembler context. If not, it - * returns NULL. + * returns NULL. This function is equivalent to calling LLVMCreateDisasmCPU() + * with an empty CPU name. */ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, int TagType, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp); /** + * Create a disassembler for the TripleName and a specific CPU. Symbolic + * disassembly is supported by passing a block of information in the DisInfo + * parameter and specifying the TagType and callback functions as described + * above. These can all be passed * as NULL. If successful, this returns a + * disassembler context. If not, it returns NULL. + */ +LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, + void *DisInfo, int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp); + +/** + * Set the disassembler's options. Returns 1 if it can set the Options and 0 + * otherwise. + */ +int LLVMSetDisasmOptions(LLVMDisasmContextRef DC, uint64_t Options); + +/* The option to produce marked up assembly. */ +#define LLVMDisassembler_Option_UseMarkup 1 +/* The option to print immediates as hex. */ +#define LLVMDisassembler_Option_PrintImmHex 2 +/* The option use the other assembler printer variant */ +#define LLVMDisassembler_Option_AsmPrinterVariant 4 + +/** * Dispose of a disassembler context. */ void LLVMDisasmDispose(LLVMDisasmContextRef DC); diff --git a/include/llvm-c/EnhancedDisassembly.h b/include/llvm-c/EnhancedDisassembly.h deleted file mode 100644 index 71a0d49..0000000 --- a/include/llvm-c/EnhancedDisassembly.h +++ /dev/null @@ -1,530 +0,0 @@ -/*===-- llvm-c/EnhancedDisassembly.h - Disassembler 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 header declares the C interface to EnhancedDisassembly.so, which *| -|* implements a disassembler with the ability to extract operand values and *| -|* individual tokens from assembly instructions. *| -|* *| -|* The header declares additional interfaces if the host compiler supports *| -|* the blocks API. *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_C_ENHANCEDDISASSEMBLY_H -#define LLVM_C_ENHANCEDDISASSEMBLY_H - -#include "llvm/Support/DataTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup LLVMCEnhancedDisassembly Enhanced Disassembly - * @ingroup LLVMC - * @deprecated - * - * This module contains an interface to the Enhanced Disassembly (edis) - * library. The edis library is deprecated and will likely disappear in - * the near future. You should use the @ref LLVMCDisassembler interface - * instead. - * - * @{ - */ - -/*! - @typedef EDByteReaderCallback - Interface to memory from which instructions may be read. - @param byte A pointer whose target should be filled in with the data returned. - @param address The address of the byte to be read. - @param arg An anonymous argument for client use. - @result 0 on success; -1 otherwise. - */ -typedef int (*EDByteReaderCallback)(uint8_t *byte, uint64_t address, void *arg); - -/*! - @typedef EDRegisterReaderCallback - Interface to registers from which registers may be read. - @param value A pointer whose target should be filled in with the value of the - register. - @param regID The LLVM register identifier for the register to read. - @param arg An anonymous argument for client use. - @result 0 if the register could be read; -1 otherwise. - */ -typedef int (*EDRegisterReaderCallback)(uint64_t *value, unsigned regID, - void* arg); - -/*! - @typedef EDAssemblySyntax_t - An assembly syntax for use in tokenizing instructions. - */ -enum { -/*! @constant kEDAssemblySyntaxX86Intel Intel syntax for i386 and x86_64. */ - kEDAssemblySyntaxX86Intel = 0, -/*! @constant kEDAssemblySyntaxX86ATT AT&T syntax for i386 and x86_64. */ - kEDAssemblySyntaxX86ATT = 1, - kEDAssemblySyntaxARMUAL = 2 -}; -typedef unsigned EDAssemblySyntax_t; - -/*! - @typedef EDDisassemblerRef - Encapsulates a disassembler for a single CPU architecture. - */ -typedef void *EDDisassemblerRef; - -/*! - @typedef EDInstRef - Encapsulates a single disassembled instruction in one assembly syntax. - */ -typedef void *EDInstRef; - -/*! - @typedef EDTokenRef - Encapsulates a token from the disassembly of an instruction. - */ -typedef void *EDTokenRef; - -/*! - @typedef EDOperandRef - Encapsulates an operand of an instruction. - */ -typedef void *EDOperandRef; - -/*! - @functiongroup Getting a disassembler - */ - -/*! - @function EDGetDisassembler - Gets the disassembler for a given target. - @param disassembler A pointer whose target will be filled in with the - disassembler. - @param triple Identifies the target. Example: "x86_64-apple-darwin10" - @param syntax The assembly syntax to use when decoding instructions. - @result 0 on success; -1 otherwise. - */ -int EDGetDisassembler(EDDisassemblerRef *disassembler, - const char *triple, - EDAssemblySyntax_t syntax); - -/*! - @functiongroup Generic architectural queries - */ - -/*! - @function EDGetRegisterName - Gets the human-readable name for a given register. - @param regName A pointer whose target will be pointed at the name of the - register. The name does not need to be deallocated and will be - @param disassembler The disassembler to query for the name. - @param regID The register identifier, as returned by EDRegisterTokenValue. - @result 0 on success; -1 otherwise. - */ -int EDGetRegisterName(const char** regName, - EDDisassemblerRef disassembler, - unsigned regID); - -/*! - @function EDRegisterIsStackPointer - Determines if a register is one of the platform's stack-pointer registers. - @param disassembler The disassembler to query. - @param regID The register identifier, as returned by EDRegisterTokenValue. - @result 1 if true; 0 otherwise. - */ -int EDRegisterIsStackPointer(EDDisassemblerRef disassembler, - unsigned regID); - -/*! - @function EDRegisterIsProgramCounter - Determines if a register is one of the platform's stack-pointer registers. - @param disassembler The disassembler to query. - @param regID The register identifier, as returned by EDRegisterTokenValue. - @result 1 if true; 0 otherwise. - */ -int EDRegisterIsProgramCounter(EDDisassemblerRef disassembler, - unsigned regID); - -/*! - @functiongroup Creating and querying instructions - */ - -/*! - @function EDCreateInst - Gets a set of contiguous instructions from a disassembler. - @param insts A pointer to an array that will be filled in with the - instructions. Must have at least count entries. Entries not filled in will - be set to NULL. - @param count The maximum number of instructions to fill in. - @param disassembler The disassembler to use when decoding the instructions. - @param byteReader The function to use when reading the instruction's machine - code. - @param address The address of the first byte of the instruction. - @param arg An anonymous argument to be passed to byteReader. - @result The number of instructions read on success; 0 otherwise. - */ -unsigned int EDCreateInsts(EDInstRef *insts, - unsigned int count, - EDDisassemblerRef disassembler, - EDByteReaderCallback byteReader, - uint64_t address, - void *arg); - -/*! - @function EDReleaseInst - Frees the memory for an instruction. The instruction can no longer be accessed - after this call. - @param inst The instruction to be freed. - */ -void EDReleaseInst(EDInstRef inst); - -/*! - @function EDInstByteSize - @param inst The instruction to be queried. - @result The number of bytes in the instruction's machine-code representation. - */ -int EDInstByteSize(EDInstRef inst); - -/*! - @function EDGetInstString - Gets the disassembled text equivalent of the instruction. - @param buf A pointer whose target will be filled in with a pointer to the - string. (The string becomes invalid when the instruction is released.) - @param inst The instruction to be queried. - @result 0 on success; -1 otherwise. - */ -int EDGetInstString(const char **buf, - EDInstRef inst); - -/*! - @function EDInstID - @param instID A pointer whose target will be filled in with the LLVM identifier - for the instruction. - @param inst The instruction to be queried. - @result 0 on success; -1 otherwise. - */ -int EDInstID(unsigned *instID, EDInstRef inst); - -/*! - @function EDInstIsBranch - @param inst The instruction to be queried. - @result 1 if the instruction is a branch instruction; 0 if it is some other - type of instruction; -1 if there was an error. - */ -int EDInstIsBranch(EDInstRef inst); - -/*! - @function EDInstIsMove - @param inst The instruction to be queried. - @result 1 if the instruction is a move instruction; 0 if it is some other - type of instruction; -1 if there was an error. - */ -int EDInstIsMove(EDInstRef inst); - -/*! - @function EDBranchTargetID - @param inst The instruction to be queried. - @result The ID of the branch target operand, suitable for use with - EDCopyOperand. -1 if no such operand exists. - */ -int EDBranchTargetID(EDInstRef inst); - -/*! - @function EDMoveSourceID - @param inst The instruction to be queried. - @result The ID of the move source operand, suitable for use with - EDCopyOperand. -1 if no such operand exists. - */ -int EDMoveSourceID(EDInstRef inst); - -/*! - @function EDMoveTargetID - @param inst The instruction to be queried. - @result The ID of the move source operand, suitable for use with - EDCopyOperand. -1 if no such operand exists. - */ -int EDMoveTargetID(EDInstRef inst); - -/*! - @functiongroup Creating and querying tokens - */ - -/*! - @function EDNumTokens - @param inst The instruction to be queried. - @result The number of tokens in the instruction, or -1 on error. - */ -int EDNumTokens(EDInstRef inst); - -/*! - @function EDGetToken - Retrieves a token from an instruction. The token is valid until the - instruction is released. - @param token A pointer to be filled in with the token. - @param inst The instruction to be queried. - @param index The index of the token in the instruction. - @result 0 on success; -1 otherwise. - */ -int EDGetToken(EDTokenRef *token, - EDInstRef inst, - int index); - -/*! - @function EDGetTokenString - Gets the disassembled text for a token. - @param buf A pointer whose target will be filled in with a pointer to the - string. (The string becomes invalid when the token is released.) - @param token The token to be queried. - @result 0 on success; -1 otherwise. - */ -int EDGetTokenString(const char **buf, - EDTokenRef token); - -/*! - @function EDOperandIndexForToken - Returns the index of the operand to which a token belongs. - @param token The token to be queried. - @result The operand index on success; -1 otherwise - */ -int EDOperandIndexForToken(EDTokenRef token); - -/*! - @function EDTokenIsWhitespace - @param token The token to be queried. - @result 1 if the token is whitespace; 0 if not; -1 on error. - */ -int EDTokenIsWhitespace(EDTokenRef token); - -/*! - @function EDTokenIsPunctuation - @param token The token to be queried. - @result 1 if the token is punctuation; 0 if not; -1 on error. - */ -int EDTokenIsPunctuation(EDTokenRef token); - -/*! - @function EDTokenIsOpcode - @param token The token to be queried. - @result 1 if the token is opcode; 0 if not; -1 on error. - */ -int EDTokenIsOpcode(EDTokenRef token); - -/*! - @function EDTokenIsLiteral - @param token The token to be queried. - @result 1 if the token is a numeric literal; 0 if not; -1 on error. - */ -int EDTokenIsLiteral(EDTokenRef token); - -/*! - @function EDTokenIsRegister - @param token The token to be queried. - @result 1 if the token identifies a register; 0 if not; -1 on error. - */ -int EDTokenIsRegister(EDTokenRef token); - -/*! - @function EDTokenIsNegativeLiteral - @param token The token to be queried. - @result 1 if the token is a negative signed literal; 0 if not; -1 on error. - */ -int EDTokenIsNegativeLiteral(EDTokenRef token); - -/*! - @function EDLiteralTokenAbsoluteValue - @param value A pointer whose target will be filled in with the absolute value - of the literal. - @param token The token to be queried. - @result 0 on success; -1 otherwise. - */ -int EDLiteralTokenAbsoluteValue(uint64_t *value, - EDTokenRef token); - -/*! - @function EDRegisterTokenValue - @param registerID A pointer whose target will be filled in with the LLVM - register identifier for the token. - @param token The token to be queried. - @result 0 on success; -1 otherwise. - */ -int EDRegisterTokenValue(unsigned *registerID, - EDTokenRef token); - -/*! - @functiongroup Creating and querying operands - */ - -/*! - @function EDNumOperands - @param inst The instruction to be queried. - @result The number of operands in the instruction, or -1 on error. - */ -int EDNumOperands(EDInstRef inst); - -/*! - @function EDGetOperand - Retrieves an operand from an instruction. The operand is valid until the - instruction is released. - @param operand A pointer to be filled in with the operand. - @param inst The instruction to be queried. - @param index The index of the operand in the instruction. - @result 0 on success; -1 otherwise. - */ -int EDGetOperand(EDOperandRef *operand, - EDInstRef inst, - int index); - -/*! - @function EDOperandIsRegister - @param operand The operand to be queried. - @result 1 if the operand names a register; 0 if not; -1 on error. - */ -int EDOperandIsRegister(EDOperandRef operand); - -/*! - @function EDOperandIsImmediate - @param operand The operand to be queried. - @result 1 if the operand specifies an immediate value; 0 if not; -1 on error. - */ -int EDOperandIsImmediate(EDOperandRef operand); - -/*! - @function EDOperandIsMemory - @param operand The operand to be queried. - @result 1 if the operand specifies a location in memory; 0 if not; -1 on error. - */ -int EDOperandIsMemory(EDOperandRef operand); - -/*! - @function EDRegisterOperandValue - @param value A pointer whose target will be filled in with the LLVM register ID - of the register named by the operand. - @param operand The operand to be queried. - @result 0 on success; -1 otherwise. - */ -int EDRegisterOperandValue(unsigned *value, - EDOperandRef operand); - -/*! - @function EDImmediateOperandValue - @param value A pointer whose target will be filled in with the value of the - immediate. - @param operand The operand to be queried. - @result 0 on success; -1 otherwise. - */ -int EDImmediateOperandValue(uint64_t *value, - EDOperandRef operand); - -/*! - @function EDEvaluateOperand - Evaluates an operand using a client-supplied register state accessor. Register - operands are evaluated by reading the value of the register; immediate operands - are evaluated by reporting the immediate value; memory operands are evaluated - by computing the target address (with only those relocations applied that were - already applied to the original bytes). - @param result A pointer whose target is to be filled with the result of - evaluating the operand. - @param operand The operand to be evaluated. - @param regReader The function to use when reading registers from the register - state. - @param arg An anonymous argument for client use. - @result 0 if the operand could be evaluated; -1 otherwise. - */ -int EDEvaluateOperand(uint64_t *result, - EDOperandRef operand, - EDRegisterReaderCallback regReader, - void *arg); - -#ifdef __BLOCKS__ - -/*! - @typedef EDByteBlock_t - Block-based interface to memory from which instructions may be read. - @param byte A pointer whose target should be filled in with the data returned. - @param address The address of the byte to be read. - @result 0 on success; -1 otherwise. - */ -typedef int (^EDByteBlock_t)(uint8_t *byte, uint64_t address); - -/*! - @typedef EDRegisterBlock_t - Block-based interface to registers from which registers may be read. - @param value A pointer whose target should be filled in with the value of the - register. - @param regID The LLVM register identifier for the register to read. - @result 0 if the register could be read; -1 otherwise. - */ -typedef int (^EDRegisterBlock_t)(uint64_t *value, unsigned regID); - -/*! - @typedef EDTokenVisitor_t - Block-based handler for individual tokens. - @param token The current token being read. - @result 0 to continue; 1 to stop normally; -1 on error. - */ -typedef int (^EDTokenVisitor_t)(EDTokenRef token); - -/*! @functiongroup Block-based interfaces */ - -/*! - @function EDBlockCreateInsts - Gets a set of contiguous instructions from a disassembler, using a block to - read memory. - @param insts A pointer to an array that will be filled in with the - instructions. Must have at least count entries. Entries not filled in will - be set to NULL. - @param count The maximum number of instructions to fill in. - @param disassembler The disassembler to use when decoding the instructions. - @param byteBlock The block to use when reading the instruction's machine - code. - @param address The address of the first byte of the instruction. - @result The number of instructions read on success; 0 otherwise. - */ -unsigned int EDBlockCreateInsts(EDInstRef *insts, - int count, - EDDisassemblerRef disassembler, - EDByteBlock_t byteBlock, - uint64_t address); - -/*! - @function EDBlockEvaluateOperand - Evaluates an operand using a block to read registers. - @param result A pointer whose target is to be filled with the result of - evaluating the operand. - @param operand The operand to be evaluated. - @param regBlock The block to use when reading registers from the register - state. - @result 0 if the operand could be evaluated; -1 otherwise. - */ -int EDBlockEvaluateOperand(uint64_t *result, - EDOperandRef operand, - EDRegisterBlock_t regBlock); - -/*! - @function EDBlockVisitTokens - Visits every token with a visitor. - @param inst The instruction with the tokens to be visited. - @param visitor The visitor. - @result 0 if the visit ended normally; -1 if the visitor encountered an error - or there was some other error. - */ -int EDBlockVisitTokens(EDInstRef inst, - EDTokenVisitor_t visitor); - -/** - * @} - */ - -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h index 8915040..57abfa0 100644 --- a/include/llvm-c/Target.h +++ b/include/llvm-c/Target.h @@ -145,7 +145,7 @@ static inline LLVMBool LLVMInitializeNativeTarget(void) { /*===-- Target Data -------------------------------------------------------===*/ /** Creates target data from a target layout string. - See the constructor llvm::TargetData::TargetData. */ + See the constructor llvm::DataLayout::DataLayout. */ LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep); /** Adds target data information to a pass manager. This does not take ownership @@ -160,48 +160,58 @@ void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef, LLVMPassManagerRef); /** Converts target data to a target layout string. The string must be disposed with LLVMDisposeMessage. - See the constructor llvm::TargetData::TargetData. */ + See the constructor llvm::DataLayout::DataLayout. */ char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef); /** Returns the byte order of a target, either LLVMBigEndian or LLVMLittleEndian. - See the method llvm::TargetData::isLittleEndian. */ + See the method llvm::DataLayout::isLittleEndian. */ enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef); /** Returns the pointer size in bytes for a target. - See the method llvm::TargetData::getPointerSize. */ + See the method llvm::DataLayout::getPointerSize. */ unsigned LLVMPointerSize(LLVMTargetDataRef); +/** 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); + /** Returns the integer type that is the same size as a pointer on a target. - See the method llvm::TargetData::getIntPtrType. */ + See the method llvm::DataLayout::getIntPtrType. */ LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef); +/** 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); + /** Computes the size of a type in bytes for a target. - See the method llvm::TargetData::getTypeSizeInBits. */ + See the method llvm::DataLayout::getTypeSizeInBits. */ unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef, LLVMTypeRef); /** Computes the storage size of a type in bytes for a target. - See the method llvm::TargetData::getTypeStoreSize. */ + See the method llvm::DataLayout::getTypeStoreSize. */ unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef, LLVMTypeRef); /** Computes the ABI size of a type in bytes for a target. - See the method llvm::TargetData::getTypeAllocSize. */ + See the method llvm::DataLayout::getTypeAllocSize. */ unsigned long long LLVMABISizeOfType(LLVMTargetDataRef, LLVMTypeRef); /** Computes the ABI alignment of a type in bytes for a target. - See the method llvm::TargetData::getTypeABISize. */ + See the method llvm::DataLayout::getTypeABISize. */ unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); /** Computes the call frame alignment of a type in bytes for a target. - See the method llvm::TargetData::getTypeABISize. */ + See the method llvm::DataLayout::getTypeABISize. */ unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); /** Computes the preferred alignment of a type in bytes for a target. - See the method llvm::TargetData::getTypeABISize. */ + See the method llvm::DataLayout::getTypeABISize. */ unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); /** Computes the preferred alignment of a global variable in bytes for a target. - See the method llvm::TargetData::getPreferredAlignment. */ + See the method llvm::DataLayout::getPreferredAlignment. */ unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef, LLVMValueRef GlobalVar); @@ -216,7 +226,7 @@ unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef, LLVMTypeRef StructTy, unsigned Element); /** Deallocates a TargetData. - See the destructor llvm::TargetData::~TargetData. */ + See the destructor llvm::DataLayout::~DataLayout. */ void LLVMDisposeTargetData(LLVMTargetDataRef); /** @@ -227,15 +237,15 @@ void LLVMDisposeTargetData(LLVMTargetDataRef); } namespace llvm { - class TargetData; + class DataLayout; class TargetLibraryInfo; - inline TargetData *unwrap(LLVMTargetDataRef P) { - return reinterpret_cast<TargetData*>(P); + inline DataLayout *unwrap(LLVMTargetDataRef P) { + return reinterpret_cast<DataLayout*>(P); } - inline LLVMTargetDataRef wrap(const TargetData *P) { - return reinterpret_cast<LLVMTargetDataRef>(const_cast<TargetData*>(P)); + inline LLVMTargetDataRef wrap(const DataLayout *P) { + return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout*>(P)); } inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) { diff --git a/include/llvm-c/TargetMachine.h b/include/llvm-c/TargetMachine.h index 0d35d73..691abdf 100644 --- a/include/llvm-c/TargetMachine.h +++ b/include/llvm-c/TargetMachine.h @@ -20,6 +20,7 @@ #define LLVM_C_TARGETMACHINE_H #include "llvm-c/Core.h" +#include "llvm-c/Target.h" #ifdef __cplusplus extern "C" { @@ -104,7 +105,7 @@ char *LLVMGetTargetMachineCPU(LLVMTargetMachineRef T); LLVMDisposeMessage. */ char *LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T); -/** Returns the llvm::TargetData used for this llvm:TargetMachine. */ +/** Returns the llvm::DataLayout used for this llvm:TargetMachine. */ LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T); /** Emits an asm or object file for the given module to the filename. This diff --git a/include/llvm-c/Transforms/Vectorize.h b/include/llvm-c/Transforms/Vectorize.h index 9e7c754..68a9bdd 100644 --- a/include/llvm-c/Transforms/Vectorize.h +++ b/include/llvm-c/Transforms/Vectorize.h @@ -36,6 +36,9 @@ extern "C" { /** See llvm::createBBVectorizePass function. */ void LLVMAddBBVectorizePass(LLVMPassManagerRef PM); +/** See llvm::createLoopVectorizePass function. */ +void LLVMAddLoopVectorizePass(LLVMPassManagerRef PM); + /** * @} */ diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index f43d365..74915c0 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -291,6 +291,13 @@ lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); extern void lto_codegen_debug_options(lto_code_gen_t cg, const char *); +/** + * Initializes LLVM disassemblers. + * FIXME: This doesn't really belong here. + */ +extern void +lto_initialize_disassembler(void); + #ifdef __cplusplus } #endif diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 5a625a4..93d343a 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -327,6 +327,7 @@ namespace llvm { bool isNegative() const { return sign; } bool isPosZero() const { return isZero() && !isNegative(); } bool isNegZero() const { return isZero() && isNegative(); } + bool isDenormal() const; APFloat& operator=(const APFloat &); @@ -455,14 +456,11 @@ namespace llvm { /* The sign bit of this number. */ unsigned int sign: 1; - - /* For PPCDoubleDouble, we have a second exponent and sign (the second - significand is appended to the first one, although it would be wrong to - regard these as a single number for arithmetic purposes). These fields - are not meaningful for any other type. */ - exponent_t exponent2 : 11; - unsigned int sign2: 1; }; + + // See friend declaration above. This additional declaration is required in + // order to compile LLVM with IBM xlC compiler. + hash_code hash_value(const APFloat &Arg); } /* namespace llvm */ #endif /* LLVM_FLOAT_H */ diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 7f20e33..95cd23d 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -251,7 +251,7 @@ public: /// constructor. APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); - /// This constructor interprets the string \arg str in the given radix. The + /// This constructor interprets the string \p str in the given radix. The /// interpretation stops when the first character that is not suitable for the /// radix is encountered, or the end of the string. Acceptable radix values /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the @@ -274,7 +274,7 @@ public: initSlowCase(that); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES /// @brief Move Constructor. APInt(APInt&& that) : BitWidth(that.BitWidth), VAL(that.VAL) { that.BitWidth = 0; @@ -601,7 +601,7 @@ public: return AssignSlowCase(RHS); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES /// @brief Move assignment operator. APInt& operator=(APInt&& that) { if (!isSingleWord()) @@ -760,7 +760,7 @@ public: APInt shl(unsigned shiftAmt) const { assert(shiftAmt <= BitWidth && "Invalid shift amount"); if (isSingleWord()) { - if (shiftAmt == BitWidth) + if (shiftAmt >= BitWidth) return APInt(BitWidth, 0); // avoid undefined shift results return APInt(BitWidth, VAL << shiftAmt); } @@ -1231,7 +1231,7 @@ public: } /// This method determines how many bits are required to hold the APInt - /// equivalent of the string given by \arg str. + /// equivalent of the string given by \p str. /// @brief Get bits required for string value. static unsigned getBitsNeeded(StringRef str, uint8_t radix); @@ -1780,6 +1780,9 @@ inline APInt Not(const APInt& APIVal) { } // End of APIntOps namespace + // See friend declaration above. This additional declaration is required in + // order to compile LLVM with IBM xlC compiler. + hash_code hash_value(const APInt &Arg); } // End of llvm namespace #endif diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 048c65c..4a5e7a3 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -23,7 +23,7 @@ class APSInt : public APInt { bool IsUnsigned; public: /// Default constructor that creates an uninitialized APInt. - explicit APSInt() {} + explicit APSInt() : IsUnsigned(false) {} /// APSInt ctor - Create an APSInt with the specified width, default to /// unsigned. diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 26ec346..82cfdf4 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -98,7 +98,7 @@ public: std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES BitVector(BitVector &&RHS) : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) { RHS.Bits = 0; @@ -237,6 +237,34 @@ public: return *this; } + /// set - Efficiently set a range of bits in [I, E) + BitVector &set(unsigned I, unsigned E) { + assert(I <= E && "Attempted to set backwards range!"); + assert(E <= size() && "Attempted to set out-of-bounds range!"); + + if (I == E) return *this; + + if (I / BITWORD_SIZE == E / BITWORD_SIZE) { + BitWord EMask = 1UL << (E % BITWORD_SIZE); + BitWord IMask = 1UL << (I % BITWORD_SIZE); + BitWord Mask = EMask - IMask; + Bits[I / BITWORD_SIZE] |= Mask; + return *this; + } + + BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE); + Bits[I / BITWORD_SIZE] |= PrefixMask; + I = RoundUpToAlignment(I, BITWORD_SIZE); + + for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE) + Bits[I / BITWORD_SIZE] = ~0UL; + + BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1; + Bits[I / BITWORD_SIZE] |= PostfixMask; + + return *this; + } + BitVector &reset() { init_words(Bits, Capacity, false); return *this; @@ -247,6 +275,34 @@ public: return *this; } + /// reset - Efficiently reset a range of bits in [I, E) + BitVector &reset(unsigned I, unsigned E) { + assert(I <= E && "Attempted to reset backwards range!"); + assert(E <= size() && "Attempted to reset out-of-bounds range!"); + + if (I == E) return *this; + + if (I / BITWORD_SIZE == E / BITWORD_SIZE) { + BitWord EMask = 1UL << (E % BITWORD_SIZE); + BitWord IMask = 1UL << (I % BITWORD_SIZE); + BitWord Mask = EMask - IMask; + Bits[I / BITWORD_SIZE] &= ~Mask; + return *this; + } + + BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE); + Bits[I / BITWORD_SIZE] &= ~PrefixMask; + I = RoundUpToAlignment(I, BITWORD_SIZE); + + for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE) + Bits[I / BITWORD_SIZE] = 0UL; + + BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1; + Bits[I / BITWORD_SIZE] &= ~PostfixMask; + + return *this; + } + BitVector &flip() { for (unsigned i = 0; i < NumBitWords(size()); ++i) Bits[i] = ~Bits[i]; @@ -396,7 +452,7 @@ public: return *this; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES const BitVector &operator=(BitVector &&RHS) { if (this == &RHS) return *this; diff --git a/include/llvm/ADT/DAGDeltaAlgorithm.h b/include/llvm/ADT/DAGDeltaAlgorithm.h index e502ac4..3dd862c 100644 --- a/include/llvm/ADT/DAGDeltaAlgorithm.h +++ b/include/llvm/ADT/DAGDeltaAlgorithm.h @@ -9,8 +9,8 @@ #ifndef LLVM_ADT_DAGDELTAALGORITHM_H #define LLVM_ADT_DAGDELTAALGORITHM_H -#include <vector> #include <set> +#include <vector> namespace llvm { @@ -48,17 +48,18 @@ public: public: virtual ~DAGDeltaAlgorithm() {} - /// Run - Minimize the DAG formed by the \arg Changes vertices and the \arg - /// Dependencies edges by executing \see ExecuteOneTest() on subsets of + /// Run - Minimize the DAG formed by the \p Changes vertices and the + /// \p Dependencies edges by executing \see ExecuteOneTest() on subsets of /// changes and returning the smallest set which still satisfies the test - /// predicate and the input \arg Dependencies. + /// predicate and the input \p Dependencies. /// /// \param Changes The list of changes. /// /// \param Dependencies The list of dependencies amongst changes. For each - /// (x,y) in \arg Dependencies, both x and y must be in \arg Changes. The - /// minimization algorithm guarantees that for each tested changed set S, x - /// \in S implies y \in S. It is an error to have cyclic dependencies. + /// (x,y) in \p Dependencies, both x and y must be in \p Changes. The + /// minimization algorithm guarantees that for each tested changed set S, + /// \f$ x \in S \f$ implies \f$ y \in S \f$. It is an error to have cyclic + /// dependencies. changeset_ty Run(const changeset_ty &Changes, const std::vector<edge_ty> &Dependencies); @@ -67,7 +68,7 @@ public: const changesetlist_ty &Sets, const changeset_ty &Required) {} - /// ExecuteOneTest - Execute a single test predicate on the change set \arg S. + /// ExecuteOneTest - Execute a single test predicate on the change set \p S. virtual bool ExecuteOneTest(const changeset_ty &S) = 0; }; diff --git a/include/llvm/ADT/DeltaAlgorithm.h b/include/llvm/ADT/DeltaAlgorithm.h index 45ba198..4d07e04 100644 --- a/include/llvm/ADT/DeltaAlgorithm.h +++ b/include/llvm/ADT/DeltaAlgorithm.h @@ -9,8 +9,8 @@ #ifndef LLVM_ADT_DELTAALGORITHM_H #define LLVM_ADT_DELTAALGORITHM_H -#include <vector> #include <set> +#include <vector> namespace llvm { @@ -45,23 +45,23 @@ private: /// since we always reduce following a success. std::set<changeset_ty> FailedTestsCache; - /// GetTestResult - Get the test result for the \arg Changes from the + /// GetTestResult - Get the test result for the \p Changes from the /// cache, executing the test if necessary. /// /// \param Changes - The change set to test. /// \return - The test result. bool GetTestResult(const changeset_ty &Changes); - /// Split - Partition a set of changes \arg S into one or two subsets. + /// Split - Partition a set of changes \p S into one or two subsets. void Split(const changeset_ty &S, changesetlist_ty &Res); - /// Delta - Minimize a set of \arg Changes which has been partioned into + /// Delta - Minimize a set of \p Changes which has been partioned into /// smaller sets, by attempting to remove individual subsets. changeset_ty Delta(const changeset_ty &Changes, const changesetlist_ty &Sets); - /// Search - Search for a subset (or subsets) in \arg Sets which can be - /// removed from \arg Changes while still satisfying the predicate. + /// Search - Search for a subset (or subsets) in \p Sets which can be + /// removed from \p Changes while still satisfying the predicate. /// /// \param Res - On success, a subset of Changes which satisfies the /// predicate. @@ -74,13 +74,13 @@ protected: virtual void UpdatedSearchState(const changeset_ty &Changes, const changesetlist_ty &Sets) {} - /// ExecuteOneTest - Execute a single test predicate on the change set \arg S. + /// ExecuteOneTest - Execute a single test predicate on the change set \p S. virtual bool ExecuteOneTest(const changeset_ty &S) = 0; public: virtual ~DeltaAlgorithm(); - /// Run - Minimize the set \arg Changes by executing \see ExecuteOneTest() on + /// Run - Minimize the set \p Changes by executing \see ExecuteOneTest() on /// subsets of changes and returning the smallest set which still satisfies /// the test predicate. changeset_ty Run(const changeset_ty &Changes); diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index f60d688..01f7e90 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -14,20 +14,20 @@ #ifndef LLVM_ADT_DENSEMAP_H #define LLVM_ADT_DENSEMAP_H -#include "llvm/Support/Compiler.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/AlignOf.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/type_traits.h" -#include "llvm/ADT/DenseMapInfo.h" #include <algorithm> -#include <iterator> -#include <new> -#include <utility> #include <cassert> #include <climits> #include <cstddef> #include <cstring> +#include <iterator> +#include <new> +#include <utility> namespace llvm { @@ -75,7 +75,7 @@ public: void clear() { if (getNumEntries() == 0 && getNumTombstones() == 0) return; - + // If the capacity of the array is huge, and the # elements used is small, // shrink the array. if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) { @@ -198,7 +198,7 @@ public: return FindAndConstruct(Key).second; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES value_type& FindAndConstruct(KeyT &&Key) { BucketT *TheBucket; if (LookupBucketFor(Key, TheBucket)) @@ -383,7 +383,7 @@ private: return TheBucket; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value, BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); @@ -420,16 +420,18 @@ private: NumBuckets = getNumBuckets(); } if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { - this->grow(NumBuckets); + this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); } + assert(TheBucket); // Only update the state after we've grown our bucket space appropriately // so that when growing buckets we have self-consistent entry count. incrementNumEntries(); // If we are writing over a tombstone, remember this. - if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey())) + const KeyT EmptyKey = getEmptyKey(); + if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey)) decrementNumTombstones(); return TheBucket; @@ -530,13 +532,13 @@ public: init(NumInitBuckets); } - DenseMap(const DenseMap &other) { + DenseMap(const DenseMap &other) : BaseT() { init(0); copyFrom(other); } -#if LLVM_USE_RVALUE_REFERENCES - DenseMap(DenseMap &&other) { +#if LLVM_HAS_RVALUE_REFERENCES + DenseMap(DenseMap &&other) : BaseT() { init(0); swap(other); } @@ -565,7 +567,7 @@ public: return *this; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES DenseMap& operator=(DenseMap &&other) { this->destroyAll(); operator delete(Buckets); @@ -599,7 +601,7 @@ public: unsigned OldNumBuckets = NumBuckets; BucketT *OldBuckets = Buckets; - allocateBuckets(std::max<unsigned>(64, NextPowerOf2(AtLeast))); + allocateBuckets(std::max<unsigned>(64, NextPowerOf2(AtLeast-1))); assert(Buckets); if (!OldBuckets) { this->BaseT::initEmpty(); @@ -699,7 +701,7 @@ public: copyFrom(other); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES SmallDenseMap(SmallDenseMap &&other) { init(0); swap(other); @@ -794,7 +796,7 @@ public: return *this; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES SmallDenseMap& operator=(SmallDenseMap &&other) { this->destroyAll(); deallocateBuckets(); @@ -825,11 +827,11 @@ public: } void grow(unsigned AtLeast) { - if (AtLeast > InlineBuckets) - AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast)); + if (AtLeast >= InlineBuckets) + AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1)); if (Small) { - if (AtLeast <= InlineBuckets) + if (AtLeast < InlineBuckets) return; // Nothing to do. // First move the inline buckets into a temporary storage. @@ -1026,7 +1028,7 @@ private: ++Ptr; } }; - + template<typename KeyT, typename ValueT, typename KeyInfoT> static inline size_t capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) { diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index 8ab9a33..d699ad5 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -32,8 +32,10 @@ public: bool empty() const { return TheMap.empty(); } unsigned size() const { return TheMap.size(); } + size_t getMemorySize() const { return TheMap.getMemorySize(); } - /// Grow the denseset so that it has at least Size buckets. Does not shrink + /// Grow the DenseSet so that it has at least Size buckets. Will not shrink + /// the Size of the set. void resize(size_t Size) { TheMap.resize(Size); } void clear() { diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index 519b180..6445442 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -34,8 +34,8 @@ #define LLVM_ADT_DEPTHFIRSTITERATOR_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallPtrSet.h" #include <set> #include <vector> diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index 771476c..1d81772 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -33,6 +33,7 @@ namespace llvm { /// /// Here is a simple example using integers: /// +/// \code /// EquivalenceClasses<int> EC; /// EC.unionSets(1, 2); // insert 1, 2 into the same set /// EC.insert(4); EC.insert(5); // insert 4, 5 into own sets @@ -46,6 +47,7 @@ namespace llvm { /// cerr << *MI << " "; // Print member. /// cerr << "\n"; // Finish set. /// } +/// \endcode /// /// This example prints: /// 4 diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 375d84a..91794de 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -16,9 +16,9 @@ #ifndef LLVM_ADT_FOLDINGSET_H #define LLVM_ADT_FOLDINGSET_H -#include "llvm/Support/DataTypes.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class APFloat; diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index 2363304..cda31a2 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -710,7 +710,7 @@ hash_code hash_combine(const T1 &arg1) { #endif -// Implementation details for implementatinos of hash_value overloads provided +// Implementation details for implementations of hash_value overloads provided // here. namespace hashing { namespace detail { diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index d7c0074..998d785 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -14,8 +14,8 @@ #ifndef LLVM_ADT_IMLIST_H #define LLVM_ADT_IMLIST_H -#include "llvm/Support/Allocator.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" #include <cassert> @@ -33,9 +33,8 @@ class ImmutableListImpl : public FoldingSetNode { friend class ImmutableListFactory<T>; - // Do not implement. - void operator=(const ImmutableListImpl&); - ImmutableListImpl(const ImmutableListImpl&); + void operator=(const ImmutableListImpl&) LLVM_DELETED_FUNCTION; + ImmutableListImpl(const ImmutableListImpl&) LLVM_DELETED_FUNCTION; public: const T& getHead() const { return Head; } diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index 8346ffa..f9baec2 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -122,8 +122,8 @@ public: } private: - Factory(const Factory& RHS); // DO NOT IMPLEMENT - void operator=(const Factory& RHS); // DO NOT IMPLEMENT + Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; + void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; }; bool contains(key_type_ref K) const { @@ -288,6 +288,13 @@ public: Factory(F) { if (Root) { Root->retain(); } } + + explicit ImmutableMapRef(const ImmutableMap<KeyT, ValT> &X, + typename ImmutableMap<KeyT, ValT>::Factory &F) + : Root(X.getRootWithoutRetain()), + Factory(F.getTreeFactory()) { + if (Root) { Root->retain(); } + } ImmutableMapRef(const ImmutableMapRef &X) : Root(X.Root), @@ -318,12 +325,20 @@ public: return ImmutableMapRef(0, F); } - ImmutableMapRef add(key_type_ref K, data_type_ref D) { + void manualRetain() { + if (Root) Root->retain(); + } + + void manualRelease() { + if (Root) Root->release(); + } + + ImmutableMapRef add(key_type_ref K, data_type_ref D) const { TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D)); return ImmutableMapRef(NewT, Factory); } - ImmutableMapRef remove(key_type_ref K) { + ImmutableMapRef remove(key_type_ref K) const { TreeTy *NewT = Factory->remove(Root, K); return ImmutableMapRef(NewT, Factory); } diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 949dc44..0982657 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -14,15 +14,14 @@ #ifndef LLVM_ADT_IMSET_H #define LLVM_ADT_IMSET_H -#include "llvm/Support/Allocator.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> #include <functional> #include <vector> -#include <stdio.h> namespace llvm { @@ -84,13 +83,13 @@ public: } return NULL; } - + /// getMaxElement - Find the subtree associated with the highest ranged /// key value. ImutAVLTree* getMaxElement() { ImutAVLTree *T = this; - ImutAVLTree *Right = T->getRight(); - while (Right) { T = right; right = T->getRight(); } + ImutAVLTree *Right = T->getRight(); + while (Right) { T = Right; Right = T->getRight(); } return T; } @@ -258,7 +257,7 @@ private: /// method returns false for an instance of ImutAVLTree, all subtrees /// will also have this method return false. The converse is not true. bool isMutable() const { return IsMutable; } - + /// hasCachedDigest - Returns true if the digest for this tree is cached. /// This can only be true if the tree is immutable. bool hasCachedDigest() const { return IsDigestCached; } @@ -280,7 +279,7 @@ private: assert(isMutable() && "Mutable flag already removed."); IsMutable = false; } - + /// markedCachedDigest - Clears the NoCachedDigest flag for a tree. void markedCachedDigest() { assert(!hasCachedDigest() && "NoCachedDigest flag already removed."); @@ -349,7 +348,7 @@ public: else factory->Cache[factory->maskCacheIndex(computeDigest())] = next; } - + // We need to clear the mutability bit in case we are // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes(). IsMutable = false; @@ -415,7 +414,7 @@ public: TreeTy* getEmptyTree() const { return NULL; } protected: - + //===--------------------------------------------------===// // A bunch of quick helper functions used for reasoning // about the properties of trees and their children. @@ -461,7 +460,7 @@ protected: // returned to the caller. //===--------------------------------------------------===// - TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) { + TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) { BumpPtrAllocator& A = getAllocator(); TreeTy* T; if (!freeNodes.empty()) { @@ -469,8 +468,7 @@ protected: freeNodes.pop_back(); assert(T != L); assert(T != R); - } - else { + } else { T = (TreeTy*) A.Allocate<TreeTy>(); } new (T) TreeTy(this, L, R, V, incrementHeight(L,R)); @@ -513,7 +511,8 @@ protected: return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R)); } - else if (hr > hl + 2) { + + if (hr > hl + 2) { assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2"); TreeTy *RL = getLeft(R); @@ -529,8 +528,8 @@ protected: return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR)); } - else - return createNode(L,V,R); + + return createNode(L,V,R); } /// add_internal - Creates a new tree that includes the specified @@ -604,7 +603,7 @@ protected: markImmutable(getLeft(T)); markImmutable(getRight(T)); } - + public: TreeTy *getCanonicalTree(TreeTy *TNew) { if (!TNew) @@ -937,7 +936,7 @@ public: private: TreeTy *Root; - + public: /// Constructs a set from a pointer to a tree root. In general one /// should use a Factory object to create sets instead of directly @@ -1006,10 +1005,10 @@ public: typename TreeTy::Factory *getTreeFactory() const { return const_cast<typename TreeTy::Factory *>(&F); } - + private: - Factory(const Factory& RHS); // DO NOT IMPLEMENT - void operator=(const Factory& RHS); // DO NOT IMPLEMENT + Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; + void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; }; friend class Factory; @@ -1027,11 +1026,11 @@ public: return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; } - TreeTy *getRoot() { + TreeTy *getRoot() { if (Root) { Root->retain(); } return Root; } - + TreeTy *getRootWithoutRetain() const { return Root; } @@ -1092,7 +1091,7 @@ public: void validateTree() const { if (Root) Root->validateTree(); } }; - + // NOTE: This may some day replace the current ImmutableSet. template <typename ValT, typename ValInfo = ImutContainerInfo<ValT> > class ImmutableSetRef { @@ -1101,11 +1100,11 @@ public: typedef typename ValInfo::value_type_ref value_type_ref; typedef ImutAVLTree<ValInfo> TreeTy; typedef typename TreeTy::Factory FactoryTy; - + private: TreeTy *Root; FactoryTy *Factory; - + public: /// Constructs a set from a pointer to a tree root. In general one /// should use a Factory object to create sets instead of directly @@ -1133,44 +1132,44 @@ public: ~ImmutableSetRef() { if (Root) { Root->release(); } } - + static inline ImmutableSetRef getEmptySet(FactoryTy *F) { return ImmutableSetRef(0, F); } - + ImmutableSetRef add(value_type_ref V) { return ImmutableSetRef(Factory->add(Root, V), Factory); } - + ImmutableSetRef remove(value_type_ref V) { return ImmutableSetRef(Factory->remove(Root, V), Factory); } - + /// Returns true if the set contains the specified value. bool contains(value_type_ref V) const { return Root ? Root->contains(V) : false; } - + ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const { return ImmutableSet<ValT>(canonicalize ? Factory->getCanonicalTree(Root) : Root); } - + TreeTy *getRootWithoutRetain() const { return Root; } - + bool operator==(const ImmutableSetRef &RHS) const { return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; } - + bool operator!=(const ImmutableSetRef &RHS) const { return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; } /// isEmpty - Return true if the set contains no elements. bool isEmpty() const { return !Root; } - + /// isSingleton - Return true if the set contains exactly one element. /// This method runs in constant time. bool isSingleton() const { return getHeight() == 1; } @@ -1178,7 +1177,7 @@ public: //===--------------------------------------------------===// // Iterators. //===--------------------------------------------------===// - + class iterator { typename TreeTy::iterator itr; iterator(TreeTy* t) : itr(t) {} @@ -1194,28 +1193,28 @@ public: inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } inline value_type *operator->() const { return &(operator*()); } }; - + iterator begin() const { return iterator(Root); } iterator end() const { return iterator(); } - + //===--------------------------------------------------===// // Utility methods. //===--------------------------------------------------===// - + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } - + static inline void Profile(FoldingSetNodeID& ID, const ImmutableSetRef& S) { ID.AddPointer(S.Root); } - + inline void Profile(FoldingSetNodeID& ID) const { return Profile(ID,*this); } - + //===--------------------------------------------------===// // For testing. //===--------------------------------------------------===// - + void validateTree() const { if (Root) Root->validateTree(); } }; diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index 931b67e..c4083ee 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -99,8 +99,8 @@ #ifndef LLVM_ADT_INTERVALMAP_H #define LLVM_ADT_INTERVALMAP_H -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/RecyclingAllocator.h" #include <iterator> @@ -151,6 +151,26 @@ struct IntervalMapInfo { }; +template <typename T> +struct IntervalMapHalfOpenInfo { + + /// startLess - Return true if x is not in [a;b). + static inline bool startLess(const T &x, const T &a) { + return x < a; + } + + /// stopLess - Return true if x is not in [a;b). + static inline bool stopLess(const T &b, const T &x) { + return b <= x; + } + + /// adjacent - Return true when the intervals [x;a) and [b;y) can coalesce. + static inline bool adjacent(const T &a, const T &b) { + return a == b; + } + +}; + /// IntervalMapImpl - Namespace used for IntervalMap implementation details. /// It should be considered private to the implementation. namespace IntervalMapImpl { diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index a9724ee..5849503 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -123,7 +123,7 @@ namespace llvm { retain(); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { S.Obj = 0; } diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h new file mode 100644 index 0000000..c34e32a --- /dev/null +++ b/include/llvm/ADT/MapVector.h @@ -0,0 +1,107 @@ +//===- llvm/ADT/MapVector.h - Map with deterministic value order *- 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 map that provides insertion order iteration. The +// interface is purposefully minimal. The key is assumed to be cheap to copy +// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in +// a std::vector. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_MAPVECTOR_H +#define LLVM_ADT_MAPVECTOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include <vector> + +namespace llvm { + +/// This class implements a map that also provides access to all stored values +/// in a deterministic order. The values are kept in a std::vector and the +/// mapping is done with DenseMap from Keys to indexes in that vector. +template<typename KeyT, typename ValueT, + typename MapType = llvm::DenseMap<KeyT, unsigned>, + typename VectorType = std::vector<std::pair<KeyT, ValueT> > > +class MapVector { + typedef typename VectorType::size_type SizeType; + + MapType Map; + VectorType Vector; + +public: + typedef typename VectorType::iterator iterator; + typedef typename VectorType::const_iterator const_iterator; + + SizeType size() const { + return Vector.size(); + } + + iterator begin() { + return Vector.begin(); + } + + const_iterator begin() const { + return Vector.begin(); + } + + iterator end() { + return Vector.end(); + } + + const_iterator end() const { + return Vector.end(); + } + + bool empty() const { + return Vector.empty(); + } + + void clear() { + Map.clear(); + Vector.clear(); + } + + ValueT &operator[](const KeyT &Key) { + std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0); + std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); + unsigned &I = Result.first->second; + if (Result.second) { + Vector.push_back(std::make_pair(Key, ValueT())); + I = Vector.size() - 1; + } + return Vector[I].second; + } + + ValueT lookup(const KeyT &Key) const { + typename MapType::const_iterator Pos = Map.find(Key); + return Pos == Map.end()? ValueT() : Vector[Pos->second].second; + } + + unsigned count(const KeyT &Key) const { + typename MapType::const_iterator Pos = Map.find(Key); + return Pos == Map.end()? 0 : 1; + } + + iterator find(const KeyT &Key) { + typename MapType::const_iterator Pos = Map.find(Key); + return Pos == Map.end()? Vector.end() : + (Vector.begin() + Pos->second); + } + + const_iterator find(const KeyT &Key) const { + typename MapType::const_iterator Pos = Map.find(Key); + return Pos == Map.end()? Vector.end() : + (Vector.begin() + Pos->second); + } +}; + +} + +#endif diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index ee8b69f..06e5af0 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -16,18 +16,27 @@ #ifndef LLVM_ADT_OPTIONAL #define LLVM_ADT_OPTIONAL +#include "llvm/Support/Compiler.h" #include <cassert> +#if LLVM_HAS_RVALUE_REFERENCES +#include <utility> +#endif + namespace llvm { template<typename T> class Optional { T x; - unsigned hasVal : 1; + bool hasVal; public: explicit Optional() : x(), hasVal(false) {} Optional(const T &y) : x(y), hasVal(true) {} +#if LLVM_HAS_RVALUE_REFERENCES + Optional(T &&y) : x(std::forward<T>(y)), hasVal(true) {} +#endif + static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } @@ -39,12 +48,17 @@ public: } const T* getPointer() const { assert(hasVal); return &x; } - const T& getValue() const { assert(hasVal); return x; } + const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return x; } operator bool() const { return hasVal; } bool hasValue() const { return hasVal; } const T* operator->() const { return getPointer(); } - const T& operator*() const { assert(hasVal); return x; } + const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return x; } + +#if LLVM_HAS_RVALUE_REFERENCE_THIS + T&& getValue() && { assert(hasVal); return std::move(x); } + T&& operator*() && { assert(hasVal); return std::move(x); } +#endif }; template<typename T> struct simplify_type; diff --git a/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h index 6d9c305..ea22991 100644 --- a/include/llvm/ADT/OwningPtr.h +++ b/include/llvm/ADT/OwningPtr.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_OWNING_PTR_H #define LLVM_ADT_OWNING_PTR_H +#include "llvm/Support/Compiler.h" #include <cassert> #include <cstddef> @@ -25,12 +26,21 @@ namespace llvm { /// pointee object can be taken away from OwningPtr by using the take method. template<class T> class OwningPtr { - OwningPtr(OwningPtr const &); // DO NOT IMPLEMENT - OwningPtr &operator=(OwningPtr const &); // DO NOT IMPLEMENT + OwningPtr(OwningPtr const &) LLVM_DELETED_FUNCTION; + OwningPtr &operator=(OwningPtr const &) LLVM_DELETED_FUNCTION; T *Ptr; public: explicit OwningPtr(T *P = 0) : Ptr(P) {} +#if LLVM_HAS_RVALUE_REFERENCES + OwningPtr(OwningPtr &&Other) : Ptr(Other.take()) {} + + OwningPtr &operator=(OwningPtr &&Other) { + reset(Other.take()); + return *this; + } +#endif + ~OwningPtr() { delete Ptr; } @@ -79,12 +89,21 @@ inline void swap(OwningPtr<T> &a, OwningPtr<T> &b) { /// functionality as OwningPtr, except that it works for array types. template<class T> class OwningArrayPtr { - OwningArrayPtr(OwningArrayPtr const &); // DO NOT IMPLEMENT - OwningArrayPtr &operator=(OwningArrayPtr const &); // DO NOT IMPLEMENT + OwningArrayPtr(OwningArrayPtr const &) LLVM_DELETED_FUNCTION; + OwningArrayPtr &operator=(OwningArrayPtr const &) LLVM_DELETED_FUNCTION; T *Ptr; public: explicit OwningArrayPtr(T *P = 0) : Ptr(P) {} +#if LLVM_HAS_RVALUE_REFERENCES + OwningArrayPtr(OwningArrayPtr &&Other) : Ptr(Other.take()) {} + + OwningArrayPtr &operator=(OwningArrayPtr &&Other) { + reset(Other.take()); + return *this; + } +#endif + ~OwningArrayPtr() { delete [] Ptr; } diff --git a/include/llvm/ADT/PackedVector.h b/include/llvm/ADT/PackedVector.h index 2eaddc2..1ae2a77 100644 --- a/include/llvm/ADT/PackedVector.h +++ b/include/llvm/ADT/PackedVector.h @@ -19,32 +19,32 @@ namespace llvm { -template <typename T, unsigned BitNum, bool isSigned> +template <typename T, unsigned BitNum, typename BitVectorTy, bool isSigned> class PackedVectorBase; // This won't be necessary if we can specialize members without specializing // the parent template. -template <typename T, unsigned BitNum> -class PackedVectorBase<T, BitNum, false> { +template <typename T, unsigned BitNum, typename BitVectorTy> +class PackedVectorBase<T, BitNum, BitVectorTy, false> { protected: - static T getValue(const llvm::BitVector &Bits, unsigned Idx) { + static T getValue(const BitVectorTy &Bits, unsigned Idx) { T val = T(); for (unsigned i = 0; i != BitNum; ++i) val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i)); return val; } - static void setValue(llvm::BitVector &Bits, unsigned Idx, T val) { + static void setValue(BitVectorTy &Bits, unsigned Idx, T val) { assert((val >> BitNum) == 0 && "value is too big"); for (unsigned i = 0; i != BitNum; ++i) Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i); } }; -template <typename T, unsigned BitNum> -class PackedVectorBase<T, BitNum, true> { +template <typename T, unsigned BitNum, typename BitVectorTy> +class PackedVectorBase<T, BitNum, BitVectorTy, true> { protected: - static T getValue(const llvm::BitVector &Bits, unsigned Idx) { + static T getValue(const BitVectorTy &Bits, unsigned Idx) { T val = T(); for (unsigned i = 0; i != BitNum-1; ++i) val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i)); @@ -53,7 +53,7 @@ protected: return val; } - static void setValue(llvm::BitVector &Bits, unsigned Idx, T val) { + static void setValue(BitVectorTy &Bits, unsigned Idx, T val) { if (val < 0) { val = ~val; Bits.set((Idx << (BitNum-1)) + BitNum-1); @@ -71,11 +71,12 @@ protected: /// @endcode /// will create a vector accepting values -2, -1, 0, 1. Any other value will hit /// an assertion. -template <typename T, unsigned BitNum> -class PackedVector : public PackedVectorBase<T, BitNum, +template <typename T, unsigned BitNum, typename BitVectorTy = BitVector> +class PackedVector : public PackedVectorBase<T, BitNum, BitVectorTy, std::numeric_limits<T>::is_signed> { - llvm::BitVector Bits; - typedef PackedVectorBase<T, BitNum, std::numeric_limits<T>::is_signed> base; + BitVectorTy Bits; + typedef PackedVectorBase<T, BitNum, BitVectorTy, + std::numeric_limits<T>::is_signed> base; public: class reference { diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 71c379b..cce2efb 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -57,11 +57,13 @@ class PointerIntPair { }; public: PointerIntPair() : Value(0) {} - PointerIntPair(PointerTy Ptr, IntType Int) : Value(0) { + PointerIntPair(PointerTy Ptr, IntType Int) { assert(IntBits <= PtrTraits::NumLowBitsAvailable && "PointerIntPair formed with integer size too large for pointer"); - setPointer(Ptr); - setInt(Int); + setPointerAndInt(Ptr, Int); + } + explicit PointerIntPair(PointerTy Ptr) { + initWithPointer(Ptr); } PointerTy getPointer() const { @@ -91,6 +93,25 @@ public: Value |= IntVal << IntShift; // Set new integer. } + void initWithPointer(PointerTy Ptr) { + intptr_t PtrVal + = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr)); + assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + "Pointer is not sufficiently aligned"); + Value = PtrVal; + } + + void setPointerAndInt(PointerTy Ptr, IntType Int) { + intptr_t PtrVal + = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr)); + assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + "Pointer is not sufficiently aligned"); + intptr_t IntVal = Int; + assert(IntVal < (1 << IntBits) && "Integer too large for field"); + + Value = PtrVal | (IntVal << IntShift); + } + PointerTy const *getAddrOfPointer() const { return const_cast<PointerIntPair *>(this)->getAddrOfPointer(); } diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index a9e86d2..f42515a 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -95,15 +95,11 @@ namespace llvm { public: PointerUnion() {} - PointerUnion(PT1 V) { - Val.setPointer( - const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))); - Val.setInt(0); + PointerUnion(PT1 V) : Val( + const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) { } - PointerUnion(PT2 V) { - Val.setPointer( - const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V))); - Val.setInt(1); + PointerUnion(PT2 V) : Val( + const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) { } /// isNull - Return true if the pointer held in the union is null, @@ -160,15 +156,14 @@ namespace llvm { /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion &operator=(const PT1 &RHS) { - Val.setPointer( + Val.initWithPointer( const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); - Val.setInt(0); return *this; } const PointerUnion &operator=(const PT2 &RHS) { - Val.setPointer( - const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS))); - Val.setInt(1); + Val.setPointerAndInt( + const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)), + 1); return *this; } diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h index 48436c6..8ce4fd5 100644 --- a/include/llvm/ADT/SCCIterator.h +++ b/include/llvm/ADT/SCCIterator.h @@ -21,8 +21,8 @@ #ifndef LLVM_ADT_SCCITERATOR_H #define LLVM_ADT_SCCITERATOR_H -#include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/GraphTraits.h" #include <vector> namespace llvm { diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index aee500d..dacda36 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -246,10 +246,10 @@ inline int array_pod_sort_comparator(const void *P1, const void *P2) { return 0; } -/// get_array_pad_sort_comparator - This is an internal helper function used to +/// get_array_pod_sort_comparator - This is an internal helper function used to /// get type deduction of T right. template<typename T> -inline int (*get_array_pad_sort_comparator(const T &)) +inline int (*get_array_pod_sort_comparator(const T &)) (const void*, const void*) { return array_pod_sort_comparator<T>; } @@ -274,7 +274,7 @@ inline void array_pod_sort(IteratorTy Start, IteratorTy End) { // Don't dereference start iterator of empty sequence. if (Start == End) return; qsort(&*Start, End-Start, sizeof(*Start), - get_array_pad_sort_comparator(*Start)); + get_array_pod_sort_comparator(*Start)); } template<class IteratorTy> diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index a6803ee..efddd9f 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -90,8 +90,8 @@ class ScopedHashTableScope { /// LastValInScope - This is the last value that was inserted for this scope /// or null if none have been inserted yet. ScopedHashTableVal<K, V> *LastValInScope; - void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT - ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT + void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; + ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; public: ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT); ~ScopedHashTableScope(); diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index 965f0de..d2f7286 100644 --- a/include/llvm/ADT/SetVector.h +++ b/include/llvm/ADT/SetVector.h @@ -27,10 +27,11 @@ namespace llvm { +/// \brief A vector that has set insertion semantics. +/// /// This adapter class provides a way to keep a set of things that also has the /// property of a deterministic iteration order. The order of iteration is the /// order of insertion. -/// @brief A vector that has set insertion semantics. template <typename T, typename Vector = std::vector<T>, typename Set = SmallSet<T, 16> > class SetVector { @@ -45,59 +46,59 @@ public: typedef typename vector_type::const_iterator const_iterator; typedef typename vector_type::size_type size_type; - /// @brief Construct an empty SetVector + /// \brief Construct an empty SetVector SetVector() {} - /// @brief Initialize a SetVector with a range of elements + /// \brief Initialize a SetVector with a range of elements template<typename It> SetVector(It Start, It End) { insert(Start, End); } - /// @brief Determine if the SetVector is empty or not. + /// \brief Determine if the SetVector is empty or not. bool empty() const { return vector_.empty(); } - /// @brief Determine the number of elements in the SetVector. + /// \brief Determine the number of elements in the SetVector. size_type size() const { return vector_.size(); } - /// @brief Get an iterator to the beginning of the SetVector. + /// \brief Get an iterator to the beginning of the SetVector. iterator begin() { return vector_.begin(); } - /// @brief Get a const_iterator to the beginning of the SetVector. + /// \brief Get a const_iterator to the beginning of the SetVector. const_iterator begin() const { return vector_.begin(); } - /// @brief Get an iterator to the end of the SetVector. + /// \brief Get an iterator to the end of the SetVector. iterator end() { return vector_.end(); } - /// @brief Get a const_iterator to the end of the SetVector. + /// \brief Get a const_iterator to the end of the SetVector. const_iterator end() const { return vector_.end(); } - /// @brief Return the last element of the SetVector. + /// \brief Return the last element of the SetVector. const T &back() const { assert(!empty() && "Cannot call back() on empty SetVector!"); return vector_.back(); } - /// @brief Index into the SetVector. + /// \brief Index into the SetVector. const_reference operator[](size_type n) const { assert(n < vector_.size() && "SetVector access out of range!"); return vector_[n]; } - /// @returns true iff the element was inserted into the SetVector. - /// @brief Insert a new element into the SetVector. + /// \brief Insert a new element into the SetVector. + /// \returns true iff the element was inserted into the SetVector. bool insert(const value_type &X) { bool result = set_.insert(X); if (result) @@ -105,7 +106,7 @@ public: return result; } - /// @brief Insert a range of elements into the SetVector. + /// \brief Insert a range of elements into the SetVector. template<typename It> void insert(It Start, It End) { for (; Start != End; ++Start) @@ -113,7 +114,7 @@ public: vector_.push_back(*Start); } - /// @brief Remove an item from the set vector. + /// \brief Remove an item from the set vector. bool remove(const value_type& X) { if (set_.erase(X)) { typename vector_type::iterator I = @@ -125,20 +126,44 @@ public: return false; } - - /// @returns 0 if the element is not in the SetVector, 1 if it is. - /// @brief Count the number of elements of a given key in the SetVector. + /// \brief Remove items from the set vector based on a predicate function. + /// + /// This is intended to be equivalent to the following code, if we could + /// write it: + /// + /// \code + /// V.erase(std::remove_if(V.begin(), V.end(), P), V.end()); + /// \endcode + /// + /// However, SetVector doesn't expose non-const iterators, making any + /// algorithm like remove_if impossible to use. + /// + /// \returns true if any element is removed. + template <typename UnaryPredicate> + bool remove_if(UnaryPredicate P) { + typename vector_type::iterator I + = std::remove_if(vector_.begin(), vector_.end(), + TestAndEraseFromSet<UnaryPredicate>(P, set_)); + if (I == vector_.end()) + return false; + vector_.erase(I, vector_.end()); + return true; + } + + + /// \brief Count the number of elements of a given key in the SetVector. + /// \returns 0 if the element is not in the SetVector, 1 if it is. size_type count(const key_type &key) const { return set_.count(key); } - /// @brief Completely clear the SetVector + /// \brief Completely clear the SetVector void clear() { set_.clear(); vector_.clear(); } - /// @brief Remove the last element of the SetVector. + /// \brief Remove the last element of the SetVector. void pop_back() { assert(!empty() && "Cannot remove an element from an empty SetVector!"); set_.erase(back()); @@ -160,18 +185,41 @@ public: } private: + /// \brief A wrapper predicate designed for use with std::remove_if. + /// + /// This predicate wraps a predicate suitable for use with std::remove_if to + /// call set_.erase(x) on each element which is slated for removal. + template <typename UnaryPredicate> + class TestAndEraseFromSet { + UnaryPredicate P; + set_type &set_; + + public: + typedef typename UnaryPredicate::argument_type argument_type; + + TestAndEraseFromSet(UnaryPredicate P, set_type &set_) : P(P), set_(set_) {} + + bool operator()(argument_type Arg) { + if (P(Arg)) { + set_.erase(Arg); + return true; + } + return false; + } + }; + set_type set_; ///< The set. vector_type vector_; ///< The vector. }; -/// SmallSetVector - A SetVector that performs no allocations if smaller than +/// \brief A SetVector that performs no allocations if smaller than /// a certain size. template <typename T, unsigned N> class SmallSetVector : public SetVector<T, SmallVector<T, N>, SmallSet<T, N> > { public: SmallSetVector() {} - /// @brief Initialize a SmallSetVector with a range of elements + /// \brief Initialize a SmallSetVector with a range of elements template<typename It> SmallSetVector(It Start, It End) { this->insert(Start, End); diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 7a645e0..62620fa 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -153,7 +153,7 @@ public: switchToLarge(new BitVector(*RHS.getPointer())); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES SmallBitVector(SmallBitVector &&RHS) : X(RHS.X) { RHS.X = 1; } @@ -300,6 +300,21 @@ public: return *this; } + /// set - Efficiently set a range of bits in [I, E) + SmallBitVector &set(unsigned I, unsigned E) { + assert(I <= E && "Attempted to set backwards range!"); + assert(E <= size() && "Attempted to set out-of-bounds range!"); + if (I == E) return *this; + if (isSmall()) { + uintptr_t EMask = ((uintptr_t)1) << E; + uintptr_t IMask = ((uintptr_t)1) << I; + uintptr_t Mask = EMask - IMask; + setSmallBits(getSmallBits() | Mask); + } else + getPointer()->set(I, E); + return *this; + } + SmallBitVector &reset() { if (isSmall()) setSmallBits(0); @@ -316,6 +331,21 @@ public: return *this; } + /// reset - Efficiently reset a range of bits in [I, E) + SmallBitVector &reset(unsigned I, unsigned E) { + assert(I <= E && "Attempted to reset backwards range!"); + assert(E <= size() && "Attempted to reset out-of-bounds range!"); + if (I == E) return *this; + if (isSmall()) { + uintptr_t EMask = ((uintptr_t)1) << E; + uintptr_t IMask = ((uintptr_t)1) << I; + uintptr_t Mask = EMask - IMask; + setSmallBits(getSmallBits() & ~Mask); + } else + getPointer()->reset(I, E); + return *this; + } + SmallBitVector &flip() { if (isSmall()) setSmallBits(~getSmallBits()); @@ -442,7 +472,7 @@ public: return *this; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES const SmallBitVector &operator=(SmallBitVector &&RHS) { if (this != &RHS) { clear(); diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 498a034..3bb8830 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -15,12 +15,13 @@ #ifndef LLVM_ADT_SMALLPTRSET_H #define LLVM_ADT_SMALLPTRSET_H +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> #include <cstddef> #include <cstring> #include <iterator> -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/PointerLikeTypeTraits.h" namespace llvm { @@ -132,7 +133,7 @@ private: /// Grow - Allocate a larger backing store for the buckets and move it over. void Grow(unsigned NewSize); - void operator=(const SmallPtrSetImpl &RHS); // DO NOT IMPLEMENT. + void operator=(const SmallPtrSetImpl &RHS) LLVM_DELETED_FUNCTION; protected: /// swap - Swaps the elements of two sets. /// Note: This method assumes that both sets have the same small size. diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h index cd117f5..4eb7de8 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -14,8 +14,8 @@ #ifndef LLVM_ADT_SMALLSET_H #define LLVM_ADT_SMALLSET_H -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include <set> namespace llvm { diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h index c6f0a5b..8da99d1 100644 --- a/include/llvm/ADT/SmallString.h +++ b/include/llvm/ADT/SmallString.h @@ -44,25 +44,25 @@ public: /// @name String Assignment /// @{ - /// Assign from a repeated element + /// Assign from a repeated element. void assign(size_t NumElts, char Elt) { this->SmallVectorImpl<char>::assign(NumElts, Elt); } - /// Assign from an iterator pair + /// Assign from an iterator pair. template<typename in_iter> void assign(in_iter S, in_iter E) { this->clear(); SmallVectorImpl<char>::append(S, E); } - /// Assign from a StringRef + /// Assign from a StringRef. void assign(StringRef RHS) { this->clear(); SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); } - /// Assign from a SmallVector + /// Assign from a SmallVector. void assign(const SmallVectorImpl<char> &RHS) { this->clear(); SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); @@ -72,7 +72,7 @@ public: /// @name String Concatenation /// @{ - /// Append from an iterator pair + /// Append from an iterator pair. template<typename in_iter> void append(in_iter S, in_iter E) { SmallVectorImpl<char>::append(S, E); @@ -83,12 +83,12 @@ public: } - /// Append from a StringRef + /// Append from a StringRef. void append(StringRef RHS) { SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); } - /// Append from a SmallVector + /// Append from a SmallVector. void append(const SmallVectorImpl<char> &RHS) { SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); } @@ -97,19 +97,19 @@ public: /// @name String Comparison /// @{ - /// equals - Check for string equality, this is more efficient than - /// compare() when the relative ordering of inequal strings isn't needed. + /// Check for string equality. This is more efficient than compare() when + /// the relative ordering of inequal strings isn't needed. bool equals(StringRef RHS) const { return str().equals(RHS); } - /// equals_lower - Check for string equality, ignoring case. + /// Check for string equality, ignoring case. bool equals_lower(StringRef RHS) const { return str().equals_lower(RHS); } - /// compare - Compare two strings; the result is -1, 0, or 1 if this string - /// is lexicographically less than, equal to, or greater than the \arg RHS. + /// Compare two strings; the result is -1, 0, or 1 if this string is + /// lexicographically less than, equal to, or greater than the \p RHS. int compare(StringRef RHS) const { return str().compare(RHS); } @@ -129,12 +129,12 @@ public: /// @name String Predicates /// @{ - /// startswith - Check if this string starts with the given \arg Prefix. + /// startswith - Check if this string starts with the given \p Prefix. bool startswith(StringRef Prefix) const { return str().startswith(Prefix); } - /// endswith - Check if this string ends with the given \arg Suffix. + /// endswith - Check if this string ends with the given \p Suffix. bool endswith(StringRef Suffix) const { return str().endswith(Suffix); } @@ -143,76 +143,76 @@ public: /// @name String Searching /// @{ - /// find - Search for the first character \arg C in the string. + /// find - Search for the first character \p C in the string. /// - /// \return - The index of the first occurrence of \arg C, or npos if not + /// \return - The index of the first occurrence of \p C, or npos if not /// found. size_t find(char C, size_t From = 0) const { return str().find(C, From); } - /// find - Search for the first string \arg Str in the string. + /// Search for the first string \p Str in the string. /// - /// \return - The index of the first occurrence of \arg Str, or npos if not + /// \returns The index of the first occurrence of \p Str, or npos if not /// found. size_t find(StringRef Str, size_t From = 0) const { return str().find(Str, From); } - /// rfind - Search for the last character \arg C in the string. + /// Search for the last character \p C in the string. /// - /// \return - The index of the last occurrence of \arg C, or npos if not + /// \returns The index of the last occurrence of \p C, or npos if not /// found. size_t rfind(char C, size_t From = StringRef::npos) const { return str().rfind(C, From); } - /// rfind - Search for the last string \arg Str in the string. + /// Search for the last string \p Str in the string. /// - /// \return - The index of the last occurrence of \arg Str, or npos if not + /// \returns The index of the last occurrence of \p Str, or npos if not /// found. size_t rfind(StringRef Str) const { return str().rfind(Str); } - /// find_first_of - Find the first character in the string that is \arg C, - /// or npos if not found. Same as find. + /// Find the first character in the string that is \p C, or npos if not + /// found. Same as find. size_t find_first_of(char C, size_t From = 0) const { return str().find_first_of(C, From); } - /// find_first_of - Find the first character in the string that is in \arg - /// Chars, or npos if not found. + /// Find the first character in the string that is in \p Chars, or npos if + /// not found. /// - /// Note: O(size() + Chars.size()) + /// Complexity: O(size() + Chars.size()) size_t find_first_of(StringRef Chars, size_t From = 0) const { return str().find_first_of(Chars, From); } - /// find_first_not_of - Find the first character in the string that is not - /// \arg C or npos if not found. + /// Find the first character in the string that is not \p C or npos if not + /// found. size_t find_first_not_of(char C, size_t From = 0) const { return str().find_first_not_of(C, From); } - /// find_first_not_of - Find the first character in the string that is not - /// in the string \arg Chars, or npos if not found. + /// Find the first character in the string that is not in the string + /// \p Chars, or npos if not found. /// - /// Note: O(size() + Chars.size()) + /// Complexity: O(size() + Chars.size()) size_t find_first_not_of(StringRef Chars, size_t From = 0) const { return str().find_first_not_of(Chars, From); } - /// find_last_of - Find the last character in the string that is \arg C, or - /// npos if not found. + /// Find the last character in the string that is \p C, or npos if not + /// found. size_t find_last_of(char C, size_t From = StringRef::npos) const { return str().find_last_of(C, From); } - /// find_last_of - Find the last character in the string that is in \arg C, - /// or npos if not found. + /// Find the last character in the string that is in \p C, or npos if not + /// found. /// - /// Note: O(size() + Chars.size()) + /// Complexity: O(size() + Chars.size()) size_t find_last_of( StringRef Chars, size_t From = StringRef::npos) const { return str().find_last_of(Chars, From); @@ -222,13 +222,13 @@ public: /// @name Helpful Algorithms /// @{ - /// count - Return the number of occurrences of \arg C in the string. + /// Return the number of occurrences of \p C in the string. size_t count(char C) const { return str().count(C); } - /// count - Return the number of non-overlapped occurrences of \arg Str in - /// the string. + /// Return the number of non-overlapped occurrences of \p Str in the + /// string. size_t count(StringRef Str) const { return str().count(Str); } @@ -237,36 +237,36 @@ public: /// @name Substring Operations /// @{ - /// substr - Return a reference to the substring from [Start, Start + N). + /// Return a reference to the substring from [Start, Start + N). /// - /// \param Start - The index of the starting character in the substring; if + /// \param Start The index of the starting character in the substring; if /// the index is npos or greater than the length of the string then the /// empty substring will be returned. /// - /// \param N - The number of characters to included in the substring. If N + /// \param N The number of characters to included in the substring. If \p N /// exceeds the number of characters remaining in the string, the string - /// suffix (starting with \arg Start) will be returned. + /// suffix (starting with \p Start) will be returned. StringRef substr(size_t Start, size_t N = StringRef::npos) const { return str().substr(Start, N); } - /// slice - Return a reference to the substring from [Start, End). + /// Return a reference to the substring from [Start, End). /// - /// \param Start - The index of the starting character in the substring; if + /// \param Start The index of the starting character in the substring; if /// the index is npos or greater than the length of the string then the /// empty substring will be returned. /// - /// \param End - The index following the last character to include in the - /// substring. If this is npos, or less than \arg Start, or exceeds the + /// \param End The index following the last character to include in the + /// substring. If this is npos, or less than \p Start, or exceeds the /// number of characters remaining in the string, the string suffix - /// (starting with \arg Start) will be returned. + /// (starting with \p Start) will be returned. StringRef slice(size_t Start, size_t End) const { return str().slice(Start, End); } // Extra methods. - /// Explicit conversion to StringRef + /// Explicit conversion to StringRef. StringRef str() const { return StringRef(this->begin(), this->size()); } // TODO: Make this const, if it's safe... diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 769b7dc..951e574 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -178,7 +178,7 @@ protected: /// std::move, but not all stdlibs actually provide that. template<typename It1, typename It2> static It2 move(It1 I, It1 E, It2 Dest) { -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES for (; I != E; ++I, ++Dest) *Dest = ::std::move(*I); return Dest; @@ -193,7 +193,7 @@ protected: /// std::move_backward, but not all stdlibs actually provide that. template<typename It1, typename It2> static It2 move_backward(It1 I, It1 E, It2 Dest) { -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES while (I != E) *--Dest = ::std::move(*--E); return Dest; @@ -206,7 +206,7 @@ protected: /// memory starting with "Dest", constructing elements as needed. template<typename It1, typename It2> static void uninitialized_move(It1 I, It1 E, It2 Dest) { -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES for (; I != E; ++I, ++Dest) ::new ((void*) &*Dest) T(::std::move(*I)); #else @@ -239,7 +239,7 @@ public: goto Retry; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES void push_back(T &&Elt) { if (this->EndX < this->CapacityX) { Retry: @@ -365,7 +365,7 @@ template <typename T> class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; - SmallVectorImpl(const SmallVectorImpl&); // DISABLED. + SmallVectorImpl(const SmallVectorImpl&) LLVM_DELETED_FUNCTION; public: typedef typename SuperClass::iterator iterator; typedef typename SuperClass::size_type size_type; @@ -422,7 +422,7 @@ public: } T pop_back_val() { -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES T Result = ::std::move(this->back()); #else T Result = this->back(); @@ -495,7 +495,7 @@ public: return(N); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES iterator insert(iterator I, T &&Elt) { if (I == this->end()) { // Important special case for empty vector. this->push_back(::std::move(Elt)); @@ -667,7 +667,7 @@ public: SmallVectorImpl &operator=(const SmallVectorImpl &RHS); -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES SmallVectorImpl &operator=(SmallVectorImpl &&RHS); #endif @@ -684,8 +684,8 @@ public: RHS.begin(), RHS.end()); } - /// set_size - Set the array size to \arg N, which the current array must have - /// enough capacity for. + /// Set the array size to \p N, which the current array must have enough + /// capacity for. /// /// This does not construct or destroy any elements in the vector. /// @@ -787,7 +787,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>:: return *this; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES template <typename T> SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { // Avoid self-assignment. @@ -898,7 +898,7 @@ public: return *this; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) { if (!RHS.empty()) SmallVectorImpl<T>::operator=(::std::move(RHS)); diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 791f108..306e928 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -262,6 +262,22 @@ public: } }; +template <unsigned ElementSize> +struct ilist_traits<SparseBitVectorElement<ElementSize> > + : public ilist_default_traits<SparseBitVectorElement<ElementSize> > { + typedef SparseBitVectorElement<ElementSize> Element; + + Element *createSentinel() const { return static_cast<Element *>(&Sentinel); } + static void destroySentinel(Element *) {} + + Element *provideInitialHead() const { return createSentinel(); } + Element *ensureHead(Element *) const { return createSentinel(); } + static void noteHead(Element *, Element *) {} + +private: + mutable ilist_half_node<Element> Sentinel; +}; + template <unsigned ElementSize = 128> class SparseBitVector { typedef ilist<SparseBitVectorElement<ElementSize> > ElementList; diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index dc3db4c..267a340 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -20,8 +20,8 @@ #ifndef LLVM_ADT_SPARSESET_H #define LLVM_ADT_SPARSESET_H -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" #include <limits> @@ -128,8 +128,8 @@ class SparseSet { // Disable copy construction and assignment. // This data structure is not meant to be used that way. - SparseSet(const SparseSet&); // DO NOT IMPLEMENT. - SparseSet &operator=(const SparseSet&); // DO NOT IMPLEMENT. + SparseSet(const SparseSet&) LLVM_DELETED_FUNCTION; + SparseSet &operator=(const SparseSet&) LLVM_DELETED_FUNCTION; public: typedef ValueT value_type; diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 36df5ac..9503e0f 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -14,14 +14,14 @@ #ifndef LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H -#include "llvm/Support/DataTypes.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" namespace llvm { template<typename T> class SmallVectorImpl; /// hexdigit - Return the hexadecimal character for the -/// given number \arg X (which should be less than 16). +/// given number \p X (which should be less than 16). static inline char hexdigit(unsigned X, bool LowerCase = false) { const char HexChar = LowerCase ? 'a' : 'A'; return X < 10 ? '0' + X : HexChar + X - 10; @@ -129,6 +129,25 @@ static inline unsigned HashString(StringRef Str, unsigned Result = 0) { return Result; } +/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th). +static inline StringRef getOrdinalSuffix(unsigned Val) { + // It is critically important that we do this perfectly for + // user-written sequences with over 100 elements. + switch (Val % 100) { + case 11: + case 12: + case 13: + return "th"; + default: + switch (Val % 10) { + case 1: return "st"; + case 2: return "nd"; + case 3: return "rd"; + default: return "th"; + } + } +} + } // End llvm namespace #endif diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index b4497a2..0d68d11 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -53,7 +53,7 @@ public: class StringMapImpl { protected: // Array of NumBuckets pointers to entries, null pointers are holes. - // TheTable[NumBuckets] contains a sentinel value for easy iteration. Follwed + // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed // by an array of the actual hash values as unsigned integers. StringMapEntryBase **TheTable; unsigned NumBuckets; @@ -171,7 +171,6 @@ public: return Create(KeyStart, KeyEnd, Allocator, 0); } - /// Create - Create a StringMapEntry with normal malloc/free. template<typename InitType> static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, @@ -204,7 +203,6 @@ public: return *reinterpret_cast<StringMapEntry*>(Ptr); } - /// Destroy - Destroy this StringMapEntry, releasing memory back to the /// specified allocator. template<typename AllocatorTy> @@ -290,7 +288,7 @@ public: return const_iterator(TheTable+Bucket, true); } - /// lookup - Return the entry for the specified key, or a default + /// lookup - Return the entry for the specified key, or a default /// constructed value if no such entry exists. ValueTy lookup(StringRef Key) const { const_iterator it = find(Key); @@ -427,7 +425,7 @@ public: return Ptr != RHS.Ptr; } - inline StringMapConstIterator& operator++() { // Preincrement + inline StringMapConstIterator& operator++() { // Preincrement ++Ptr; AdvancePastEmptyBuckets(); return *this; diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index cd84603..0e93f51 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -11,7 +11,6 @@ #define LLVM_ADT_STRINGREF_H #include "llvm/Support/type_traits.h" - #include <algorithm> #include <cassert> #include <cstring> @@ -138,7 +137,7 @@ namespace llvm { } /// compare - Compare two strings; the result is -1, 0, or 1 if this string - /// is lexicographically less than, equal to, or greater than the \arg RHS. + /// is lexicographically less than, equal to, or greater than the \p RHS. int compare(StringRef RHS) const { // Check the prefix for a mismatch. if (int Res = compareMemory(Data, RHS.Data, min(Length, RHS.Length))) @@ -205,13 +204,13 @@ namespace llvm { /// @name String Predicates /// @{ - /// startswith - Check if this string starts with the given \arg Prefix. + /// Check if this string starts with the given \p Prefix. bool startswith(StringRef Prefix) const { return Length >= Prefix.Length && compareMemory(Data, Prefix.Data, Prefix.Length) == 0; } - /// endswith - Check if this string ends with the given \arg Suffix. + /// 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; @@ -221,9 +220,9 @@ namespace llvm { /// @name String Searching /// @{ - /// find - Search for the first character \arg C in the string. + /// Search for the first character \p C in the string. /// - /// \return - The index of the first occurrence of \arg C, or npos if not + /// \returns The index of the first occurrence of \p C, or npos if not /// found. size_t find(char C, size_t From = 0) const { for (size_t i = min(From, Length), e = Length; i != e; ++i) @@ -232,15 +231,15 @@ namespace llvm { return npos; } - /// find - Search for the first string \arg Str in the string. + /// Search for the first string \p Str in the string. /// - /// \return - The index of the first occurrence of \arg Str, or npos if not + /// \returns The index of the first occurrence of \p Str, or npos if not /// found. size_t find(StringRef Str, size_t From = 0) const; - /// rfind - Search for the last character \arg C in the string. + /// Search for the last character \p C in the string. /// - /// \return - The index of the last occurrence of \arg C, or npos if not + /// \returns The index of the last occurrence of \p C, or npos if not /// found. size_t rfind(char C, size_t From = npos) const { From = min(From, Length); @@ -253,61 +252,61 @@ namespace llvm { return npos; } - /// rfind - Search for the last string \arg Str in the string. + /// Search for the last string \p Str in the string. /// - /// \return - The index of the last occurrence of \arg Str, or npos if not + /// \returns The index of the last occurrence of \p Str, or npos if not /// found. size_t rfind(StringRef Str) const; - /// find_first_of - Find the first character in the string that is \arg C, - /// or npos if not found. Same as find. + /// Find the first character in the string that is \p C, or npos if not + /// found. Same as find. size_type find_first_of(char C, size_t From = 0) const { return find(C, From); } - /// find_first_of - Find the first character in the string that is in \arg - /// Chars, or npos if not found. + /// Find the first character in the string that is in \p Chars, or npos if + /// not found. /// - /// Note: O(size() + Chars.size()) + /// Complexity: O(size() + Chars.size()) size_type find_first_of(StringRef Chars, size_t From = 0) const; - /// find_first_not_of - Find the first character in the string that is not - /// \arg C or npos if not found. + /// Find the first character in the string that is not \p C or npos if not + /// found. size_type find_first_not_of(char C, size_t From = 0) const; - /// find_first_not_of - Find the first character in the string that is not - /// in the string \arg Chars, or npos if not found. + /// Find the first character in the string that is not in the string + /// \p Chars, or npos if not found. /// - /// Note: O(size() + Chars.size()) + /// Complexity: O(size() + Chars.size()) size_type find_first_not_of(StringRef Chars, size_t From = 0) const; - /// find_last_of - Find the last character in the string that is \arg C, or - /// npos if not found. + /// Find the last character in the string that is \p C, or npos if not + /// found. size_type find_last_of(char C, size_t From = npos) const { return rfind(C, From); } - /// find_last_of - Find the last character in the string that is in \arg C, - /// or npos if not found. + /// Find the last character in the string that is in \p C, or npos if not + /// found. /// - /// Note: O(size() + Chars.size()) + /// Complexity: O(size() + Chars.size()) size_type find_last_of(StringRef Chars, size_t From = npos) const; - /// find_last_not_of - Find the last character in the string that is not - /// \arg C, or npos if not found. + /// Find the last character in the string that is not \p C, or npos if not + /// found. size_type find_last_not_of(char C, size_t From = npos) const; - /// find_last_not_of - Find the last character in the string that is not in - /// \arg Chars, or npos if not found. + /// Find the last character in the string that is not in \p Chars, or + /// npos if not found. /// - /// Note: O(size() + Chars.size()) + /// Complexity: O(size() + Chars.size()) size_type find_last_not_of(StringRef Chars, size_t From = npos) const; /// @} /// @name Helpful Algorithms /// @{ - /// count - Return the number of occurrences of \arg C in the string. + /// Return the number of occurrences of \p C in the string. size_t count(char C) const { size_t Count = 0; for (size_t i = 0, e = Length; i != e; ++i) @@ -316,18 +315,17 @@ namespace llvm { return Count; } - /// count - Return the number of non-overlapped occurrences of \arg Str in + /// Return the number of non-overlapped occurrences of \p Str in /// the string. size_t count(StringRef Str) const; - /// getAsInteger - Parse the current string as an integer of the specified - /// radix. If Radix is specified as zero, this does radix autosensing using + /// Parse the current string as an integer of the specified radix. If + /// \p Radix is specified as zero, this does radix autosensing using /// extended C rules: 0 is octal, 0x is hex, 0b is binary. /// /// If the string is invalid or if only a subset of the string is valid, /// this returns true to signify the error. The string is considered /// erroneous if empty or if it overflows T. - /// template <typename T> typename enable_if_c<std::numeric_limits<T>::is_signed, bool>::type getAsInteger(unsigned Radix, T &Result) const { @@ -350,13 +348,12 @@ namespace llvm { return false; } - /// getAsInteger - Parse the current string as an integer of the - /// specified radix, or of an autosensed radix if the radix given - /// is 0. The current value in Result is discarded, and the - /// storage is changed to be wide enough to store the parsed - /// integer. + /// Parse the current string as an integer of the specified \p Radix, or of + /// an autosensed radix if the \p Radix given is 0. The current value in + /// \p Result is discarded, and the storage is changed to be wide enough to + /// store the parsed integer. /// - /// Returns true if the string does not solely consist of a valid + /// \returns true if the string does not solely consist of a valid /// non-empty number in the appropriate base. /// /// APInt::fromString is superficially similar but assumes the @@ -367,70 +364,70 @@ namespace llvm { /// @name String Operations /// @{ - // lower - Convert the given ASCII string to lowercase. + // Convert the given ASCII string to lowercase. std::string lower() const; - /// upper - Convert the given ASCII string to uppercase. + /// Convert the given ASCII string to uppercase. std::string upper() const; /// @} /// @name Substring Operations /// @{ - /// substr - Return a reference to the substring from [Start, Start + N). + /// Return a reference to the substring from [Start, Start + N). /// - /// \param Start - The index of the starting character in the substring; if + /// \param Start The index of the starting character in the substring; if /// the index is npos or greater than the length of the string then the /// empty substring will be returned. /// - /// \param N - The number of characters to included in the substring. If N + /// \param N The number of characters to included in the substring. If N /// exceeds the number of characters remaining in the string, the string - /// suffix (starting with \arg Start) will be returned. + /// suffix (starting with \p Start) will be returned. StringRef substr(size_t Start, size_t N = npos) const { Start = min(Start, Length); return StringRef(Data + Start, min(N, Length - Start)); } - /// drop_front - Return a StringRef equal to 'this' but with the first - /// elements dropped. + /// Return a StringRef equal to 'this' but with the first \p N elements + /// dropped. StringRef drop_front(unsigned N = 1) const { assert(size() >= N && "Dropping more elements than exist"); return substr(N); } - /// drop_back - Return a StringRef equal to 'this' but with the last - /// elements dropped. + /// Return a StringRef equal to 'this' but with the last \p N elements + /// dropped. StringRef drop_back(unsigned N = 1) const { assert(size() >= N && "Dropping more elements than exist"); return substr(0, size()-N); } - /// slice - Return a reference to the substring from [Start, End). + /// Return a reference to the substring from [Start, End). /// - /// \param Start - The index of the starting character in the substring; if + /// \param Start The index of the starting character in the substring; if /// the index is npos or greater than the length of the string then the /// empty substring will be returned. /// - /// \param End - The index following the last character to include in the - /// substring. If this is npos, or less than \arg Start, or exceeds the + /// \param End The index following the last character to include in the + /// substring. If this is npos, or less than \p Start, or exceeds the /// number of characters remaining in the string, the string suffix - /// (starting with \arg Start) will be returned. + /// (starting with \p Start) will be returned. StringRef slice(size_t Start, size_t End) const { Start = min(Start, Length); End = min(max(Start, End), Length); return StringRef(Data + Start, End - Start); } - /// split - Split into two substrings around the first occurrence of a - /// separator character. + /// Split into two substrings around the first occurrence of a separator + /// character. /// - /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) /// such that (*this == LHS + Separator + RHS) is true and RHS is - /// maximal. If \arg Separator is not in the string, then the result is a + /// maximal. If \p Separator is not in the string, then the result is a /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). /// - /// \param Separator - The character to split on. - /// \return - The split substrings. + /// \param Separator The character to split on. + /// \returns The split substrings. std::pair<StringRef, StringRef> split(char Separator) const { size_t Idx = find(Separator); if (Idx == npos) @@ -438,12 +435,12 @@ namespace llvm { return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); } - /// split - Split into two substrings around the first occurrence of a - /// separator string. + /// Split into two substrings around the first occurrence of a separator + /// string. /// - /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) /// such that (*this == LHS + Separator + RHS) is true and RHS is - /// maximal. If \arg Separator is not in the string, then the result is a + /// maximal. If \p Separator is not in the string, then the result is a /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). /// /// \param Separator - The string to split on. @@ -455,14 +452,13 @@ namespace llvm { return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); } - /// split - Split into substrings around the occurrences of a separator - /// string. + /// Split into substrings around the occurrences of a separator string. /// - /// Each substring is stored in \arg A. If \arg MaxSplit is >= 0, at most - /// \arg MaxSplit splits are done and consequently <= \arg MaxSplit + /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most + /// \p MaxSplit splits are done and consequently <= \p MaxSplit /// elements are added to A. - /// If \arg KeepEmpty is false, empty strings are not added to \arg A. They - /// still count when considering \arg MaxSplit + /// If \p KeepEmpty is false, empty strings are not added to \p A. They + /// still count when considering \p MaxSplit /// An useful invariant is that /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true /// @@ -474,12 +470,12 @@ namespace llvm { StringRef Separator, int MaxSplit = -1, bool KeepEmpty = true) const; - /// rsplit - Split into two substrings around the last occurrence of a - /// separator character. + /// Split into two substrings around the last occurrence of a separator + /// character. /// - /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) /// such that (*this == LHS + Separator + RHS) is true and RHS is - /// minimal. If \arg Separator is not in the string, then the result is a + /// minimal. If \p Separator is not in the string, then the result is a /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). /// /// \param Separator - The character to split on. @@ -491,20 +487,20 @@ namespace llvm { return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); } - /// ltrim - Return string with consecutive characters in \arg Chars starting - /// from the left removed. + /// Return string with consecutive characters in \p Chars starting from + /// the left removed. StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { return drop_front(std::min(Length, find_first_not_of(Chars))); } - /// rtrim - Return string with consecutive characters in \arg Chars starting - /// from the right removed. + /// Return string with consecutive characters in \p Chars starting from + /// the right removed. StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); } - /// trim - Return string with consecutive characters in \arg Chars starting - /// from the left and right removed. + /// Return string with consecutive characters in \p Chars starting from + /// the left and right removed. StringRef trim(StringRef Chars = " \t\n\v\f\r") const { return ltrim(Chars).rtrim(Chars); } diff --git a/include/llvm/ADT/StringSet.h b/include/llvm/ADT/StringSet.h index 9c55f6b..b69a964 100644 --- a/include/llvm/ADT/StringSet.h +++ b/include/llvm/ADT/StringSet.h @@ -29,8 +29,13 @@ namespace llvm { assert(!InLang.empty()); const char *KeyStart = InLang.data(); const char *KeyEnd = KeyStart + InLang.size(); - return base::insert(llvm::StringMapEntry<char>:: - Create(KeyStart, KeyEnd, base::getAllocator(), '+')); + llvm::StringMapEntry<char> *Entry = llvm::StringMapEntry<char>:: + Create(KeyStart, KeyEnd, base::getAllocator(), '+'); + if (!base::insert(Entry)) { + Entry->Destroy(base::getAllocator()); + return false; + } + return true; } }; } diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index d3d33b8..cc0e7b6 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -70,7 +70,7 @@ public: return *this; } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) { RHS.Val = (EltTy)0; } diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index ab1f0da..49d9f68 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -44,7 +44,6 @@ public: UnknownArch, arm, // ARM; arm, armv.*, xscale - cellspu, // CellSPU: spu, cellspu hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel @@ -65,7 +64,9 @@ public: nvptx, // NVPTX: 32-bit nvptx64, // NVPTX: 64-bit le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) - amdil // amdil: amd IL + amdil, // amdil: amd IL + spir, // SPIR: standard portable IR for OpenCL 32-bit version + spir64 // SPIR: standard portable IR for OpenCL 64-bit version }; enum VendorType { UnknownVendor, @@ -75,7 +76,8 @@ public: SCEI, BGP, BGQ, - Freescale + Freescale, + IBM }; enum OSType { UnknownOS, @@ -98,9 +100,10 @@ public: Haiku, Minix, RTEMS, - NativeClient, - CNK, // BG/P Compute-Node Kernel - Bitrig + NaCl, // Native Client + CNK, // BG/P Compute-Node Kernel + Bitrig, + AIX }; enum EnvironmentType { UnknownEnvironment, @@ -110,7 +113,8 @@ public: GNUEABIHF, EABI, MachO, - Android + Android, + ELF }; private: @@ -306,6 +310,11 @@ public: return getOS() == Triple::Win32 || isOSCygMing(); } + /// \brief Tests whether the OS is NaCl (Native Client) + bool isOSNaCl() const { + return getOS() == Triple::NaCl; + } + /// \brief Tests whether the OS uses the ELF binary format. bool isOSBinFormatELF() const { return !isOSDarwin() && !isOSWindows(); @@ -342,7 +351,7 @@ public: /// to a known type. void setEnvironment(EnvironmentType Kind); - /// setTriple - Set all components to the new triple \arg Str. + /// setTriple - Set all components to the new triple \p Str. void setTriple(const Twine &Str); /// setArchName - Set the architecture (first) component of the @@ -393,11 +402,10 @@ public: /// @name Static helpers for IDs. /// @{ - /// getArchTypeName - Get the canonical name for the \arg Kind - /// architecture. + /// getArchTypeName - Get the canonical name for the \p Kind architecture. static const char *getArchTypeName(ArchType Kind); - /// getArchTypePrefix - Get the "prefix" canonical name for the \arg Kind + /// getArchTypePrefix - Get the "prefix" canonical name for the \p Kind /// architecture. This is the prefix used by the architecture specific /// builtins, and is suitable for passing to \see /// Intrinsic::getIntrinsicForGCCBuiltin(). @@ -405,15 +413,13 @@ public: /// \return - The architecture prefix, or 0 if none is defined. static const char *getArchTypePrefix(ArchType Kind); - /// getVendorTypeName - Get the canonical name for the \arg Kind - /// vendor. + /// getVendorTypeName - Get the canonical name for the \p Kind vendor. static const char *getVendorTypeName(VendorType Kind); - /// getOSTypeName - Get the canonical name for the \arg Kind operating - /// system. + /// getOSTypeName - Get the canonical name for the \p Kind operating system. static const char *getOSTypeName(OSType Kind); - /// getEnvironmentTypeName - Get the canonical name for the \arg Kind + /// getEnvironmentTypeName - Get the canonical name for the \p Kind /// environment. static const char *getEnvironmentTypeName(EnvironmentType Kind); @@ -425,11 +431,6 @@ public: /// architecture name (e.g., "x86"). static ArchType getArchTypeForLLVMName(StringRef Str); - /// getArchTypeForDarwinArchName - Get the architecture type for a "Darwin" - /// architecture name, for example as accepted by "gcc -arch" (see also - /// arch(3)). - static ArchType getArchTypeForDarwinArchName(StringRef Str); - /// @} }; diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 9101df8..cc290d5 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -44,7 +44,7 @@ namespace llvm { /// itself, and renders as an empty string. This can be returned from APIs to /// effectively nullify any concatenations performed on the result. /// - /// \b Implementation \n + /// \b Implementation /// /// Given the nature of a Twine, it is not possible for the Twine's /// concatenation method to construct interior nodes; the result must be @@ -67,7 +67,7 @@ namespace llvm { /// /// These invariants are check by \see isValid(). /// - /// \b Efficiency Considerations \n + /// \b Efficiency Considerations /// /// The Twine is designed to yield efficient and small code for common /// situations. For this reason, the concat() method is inlined so that @@ -303,37 +303,37 @@ namespace llvm { LHS.character = static_cast<char>(Val); } - /// Construct a twine to print \arg Val as an unsigned decimal integer. + /// Construct a twine to print \p Val as an unsigned decimal integer. explicit Twine(unsigned Val) : LHSKind(DecUIKind), RHSKind(EmptyKind) { LHS.decUI = Val; } - /// Construct a twine to print \arg Val as a signed decimal integer. + /// Construct a twine to print \p Val as a signed decimal integer. explicit Twine(int Val) : LHSKind(DecIKind), RHSKind(EmptyKind) { LHS.decI = Val; } - /// Construct a twine to print \arg Val as an unsigned decimal integer. + /// Construct a twine to print \p Val as an unsigned decimal integer. explicit Twine(const unsigned long &Val) : LHSKind(DecULKind), RHSKind(EmptyKind) { LHS.decUL = &Val; } - /// Construct a twine to print \arg Val as a signed decimal integer. + /// Construct a twine to print \p Val as a signed decimal integer. explicit Twine(const long &Val) : LHSKind(DecLKind), RHSKind(EmptyKind) { LHS.decL = &Val; } - /// Construct a twine to print \arg Val as an unsigned decimal integer. + /// Construct a twine to print \p Val as an unsigned decimal integer. explicit Twine(const unsigned long long &Val) : LHSKind(DecULLKind), RHSKind(EmptyKind) { LHS.decULL = &Val; } - /// Construct a twine to print \arg Val as a signed decimal integer. + /// Construct a twine to print \p Val as a signed decimal integer. explicit Twine(const long long &Val) : LHSKind(DecLLKind), RHSKind(EmptyKind) { LHS.decLL = &Val; @@ -370,7 +370,7 @@ namespace llvm { /// @name Numeric Conversions /// @{ - // Construct a twine to print \arg Val as an unsigned hexadecimal integer. + // Construct a twine to print \p Val as an unsigned hexadecimal integer. static Twine utohexstr(const uint64_t &Val) { Child LHS, RHS; LHS.uHex = &Val; @@ -447,17 +447,17 @@ namespace llvm { /// The returned StringRef's size does not include the null terminator. StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const; - /// print - Write the concatenated string represented by this twine to the - /// stream \arg OS. + /// Write the concatenated string represented by this twine to the + /// stream \p OS. void print(raw_ostream &OS) const; - /// dump - Dump the concatenated string represented by this twine to stderr. + /// Dump the concatenated string represented by this twine to stderr. void dump() const; - /// print - Write the representation of this twine to the stream \arg OS. + /// Write the representation of this twine to the stream \p OS. void printRepr(raw_ostream &OS) const; - /// dumpRepr - Dump the representation of this twine to stderr. + /// Dump the representation of this twine to stderr. void dumpRepr() const; /// @} diff --git a/include/llvm/ADT/ValueMap.h b/include/llvm/ADT/ValueMap.h index f7e2551..b4fed7a 100644 --- a/include/llvm/ADT/ValueMap.h +++ b/include/llvm/ADT/ValueMap.h @@ -27,10 +27,9 @@ #define LLVM_ADT_VALUEMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Mutex.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/type_traits.h" -#include "llvm/Support/Mutex.h" - #include <iterator> namespace llvm { @@ -80,8 +79,8 @@ class ValueMap { typedef typename Config::ExtraData ExtraData; MapT Map; ExtraData Data; - ValueMap(const ValueMap&); // DO NOT IMPLEMENT - ValueMap& operator=(const ValueMap&); // DO NOT IMPLEMENT + ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION; + ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION; public: typedef KeyT key_type; typedef ValueT mapped_type; diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index ba9864a..20cdae3 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -38,6 +38,7 @@ #ifndef LLVM_ADT_ILIST_H #define LLVM_ADT_ILIST_H +#include "llvm/Support/Compiler.h" #include <algorithm> #include <cassert> #include <cstddef> @@ -331,8 +332,8 @@ class iplist : public Traits { // No fundamental reason why iplist can't be copyable, but the default // copy/copy-assign won't do. - iplist(const iplist &); // do not implement - void operator=(const iplist &); // do not implement + iplist(const iplist &) LLVM_DELETED_FUNCTION; + void operator=(const iplist &) LLVM_DELETED_FUNCTION; public: typedef NodeTy *pointer; @@ -464,6 +465,17 @@ public: return where; } + /// Remove all nodes from the list like clear(), but do not call + /// removeNodeFromList() or deleteNode(). + /// + /// This should only be used immediately before freeing nodes in bulk to + /// avoid traversing the list and bringing all the nodes into cache. + void clearAndLeakNodesUnsafely() { + if (Head) { + Head = getTail(); + this->setPrev(Head, Head); + } + } private: // transfer - The heart of the splice function. Move linked list nodes from @@ -471,6 +483,10 @@ private: // void transfer(iterator position, iplist &L2, iterator first, iterator last) { assert(first != last && "Should be checked by callers"); + // Position cannot be contained in the range to be transferred. + // Check for the most common mistake. + assert(position != first && + "Insertion point can't be one of the transferred nodes"); if (position != last) { // Note: we have to be careful about the case when we move the first node diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index f587220..3ce4732 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -37,15 +37,15 @@ #ifndef LLVM_ANALYSIS_ALIAS_ANALYSIS_H #define LLVM_ANALYSIS_ALIAS_ANALYSIS_H -#include "llvm/Support/CallSite.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CallSite.h" namespace llvm { class LoadInst; class StoreInst; class VAArgInst; -class TargetData; +class DataLayout; class TargetLibraryInfo; class Pass; class AnalysisUsage; @@ -55,7 +55,7 @@ class DominatorTree; class AliasAnalysis { protected: - const TargetData *TD; + const DataLayout *TD; const TargetLibraryInfo *TLI; private: @@ -83,17 +83,17 @@ public: /// know the sizes of the potential memory references. static uint64_t const UnknownSize = ~UINT64_C(0); - /// getTargetData - Return a pointer to the current TargetData object, or - /// null if no TargetData object is available. + /// getDataLayout - Return a pointer to the current DataLayout object, or + /// null if no DataLayout object is available. /// - const TargetData *getTargetData() const { return TD; } + const DataLayout *getDataLayout() const { return TD; } /// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo /// object, or null if no TargetLibraryInfo object is available. /// const TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; } - /// getTypeStoreSize - Return the TargetData store size for the given type, + /// getTypeStoreSize - Return the DataLayout store size for the given type, /// if known, or a conservative value otherwise. /// uint64_t getTypeStoreSize(Type *Ty); @@ -373,7 +373,7 @@ public: return getModRefInfo(I, Location(P, Size)); } - /// getModRefInfo (for call sites) - Return whether information about whether + /// getModRefInfo (for call sites) - Return information about whether /// a particular call site modifies or reads the specified memory location. virtual ModRefResult getModRefInfo(ImmutableCallSite CS, const Location &Loc); @@ -384,7 +384,7 @@ public: return getModRefInfo(CS, Location(P, Size)); } - /// getModRefInfo (for calls) - Return whether information about whether + /// getModRefInfo (for calls) - Return information about whether /// a particular call modifies or reads the specified memory location. ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) { return getModRefInfo(ImmutableCallSite(C), Loc); @@ -395,7 +395,7 @@ public: return getModRefInfo(C, Location(P, Size)); } - /// getModRefInfo (for invokes) - Return whether information about whether + /// getModRefInfo (for invokes) - Return information about whether /// a particular invoke modifies or reads the specified memory location. ModRefResult getModRefInfo(const InvokeInst *I, const Location &Loc) { @@ -408,7 +408,7 @@ public: return getModRefInfo(I, Location(P, Size)); } - /// getModRefInfo (for loads) - Return whether information about whether + /// getModRefInfo (for loads) - Return information about whether /// a particular load modifies or reads the specified memory location. ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc); @@ -417,7 +417,7 @@ public: return getModRefInfo(L, Location(P, Size)); } - /// getModRefInfo (for stores) - Return whether information about whether + /// getModRefInfo (for stores) - Return information about whether /// a particular store modifies or reads the specified memory location. ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc); @@ -426,7 +426,7 @@ public: return getModRefInfo(S, Location(P, Size)); } - /// getModRefInfo (for fences) - Return whether information about whether + /// getModRefInfo (for fences) - Return information about whether /// a particular store modifies or reads the specified memory location. ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) { // Conservatively correct. (We could possibly be a bit smarter if @@ -439,7 +439,7 @@ public: return getModRefInfo(S, Location(P, Size)); } - /// getModRefInfo (for cmpxchges) - Return whether information about whether + /// getModRefInfo (for cmpxchges) - Return information about whether /// a particular cmpxchg modifies or reads the specified memory location. ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc); @@ -449,7 +449,7 @@ public: return getModRefInfo(CX, Location(P, Size)); } - /// getModRefInfo (for atomicrmws) - Return whether information about whether + /// getModRefInfo (for atomicrmws) - Return information about whether /// a particular atomicrmw modifies or reads the specified memory location. ModRefResult getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc); @@ -459,7 +459,7 @@ public: return getModRefInfo(RMW, Location(P, Size)); } - /// getModRefInfo (for va_args) - Return whether information about whether + /// getModRefInfo (for va_args) - Return information about whether /// a particular va_arg modifies or reads the specified memory location. ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc); @@ -587,9 +587,9 @@ bool isNoAliasCall(const Value *V); /// isIdentifiedObject - Return true if this pointer refers to a distinct and /// identifiable object. This returns true for: /// Global Variables and Functions (but not Global Aliases) -/// Allocas and Mallocs +/// Allocas /// ByVal and NoAlias Arguments -/// NoAlias returns +/// NoAlias returns (e.g. calls to malloc) /// bool isIdentifiedObject(const Value *V); diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index 95626d6..163331c 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -17,11 +17,11 @@ #ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H #define LLVM_ANALYSIS_ALIASSETTRACKER_H -#include "llvm/Support/CallSite.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ValueHandle.h" #include <vector> namespace llvm { @@ -109,7 +109,6 @@ class AliasSet : public ilist_node<AliasSet> { PointerRec *PtrList, **PtrListEnd; // Doubly linked list of nodes. AliasSet *Forward; // Forwarding pointer. - AliasSet *Next, *Prev; // Doubly linked list of AliasSets. // All instructions without a specific address in this alias set. std::vector<AssertingVH<Instruction> > UnknownInsts; @@ -226,8 +225,8 @@ private: AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { } - AliasSet(const AliasSet &AS); // do not implement - void operator=(const AliasSet &AS); // do not implement + AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION; + void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION; PointerRec *getSomePointer() const { return PtrList; diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h index 5168ab7..f220c58 100644 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -14,17 +14,17 @@ #ifndef LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H #define LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H -#include "llvm/BasicBlock.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/Support/BlockFrequency.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include <vector> #include <string> +#include <vector> namespace llvm { diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index c0567da..6c23f7c 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -14,10 +14,10 @@ #ifndef LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H #define LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" #include "llvm/Support/BranchProbability.h" namespace llvm { diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index 4704a92..fa596c3 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -15,10 +15,10 @@ #ifndef LLVM_ANALYSIS_CFGPRINTER_H #define LLVM_ANALYSIS_CFGPRINTER_H -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/Instructions.h" #include "llvm/Assembly/Writer.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/CFG.h" #include "llvm/Support/GraphWriter.h" diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index fb77da7..591484d 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -51,13 +51,13 @@ #ifndef LLVM_ANALYSIS_CALLGRAPH_H #define LLVM_ANALYSIS_CALLGRAPH_H -#include "llvm/Function.h" -#include "llvm/Pass.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/IR/Function.h" +#include "llvm/Pass.h" #include "llvm/Support/CallSite.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/IncludeFile.h" +#include "llvm/Support/ValueHandle.h" #include <map> namespace llvm { @@ -185,9 +185,9 @@ private: /// in the CalledFunctions array of this or other CallGraphNodes. unsigned NumReferences; - CallGraphNode(const CallGraphNode &); // DO NOT IMPLEMENT - void operator=(const CallGraphNode &); // DO NOT IMPLEMENT - + CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION; + void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION; + void DropRef() { --NumReferences; } void AddRef() { ++NumReferences; } public: diff --git a/include/llvm/CallGraphSCCPass.h b/include/llvm/Analysis/CallGraphSCCPass.h index 7154aa3..4446777 100644 --- a/include/llvm/CallGraphSCCPass.h +++ b/include/llvm/Analysis/CallGraphSCCPass.h @@ -21,8 +21,8 @@ #ifndef LLVM_CALL_GRAPH_SCC_PASS_H #define LLVM_CALL_GRAPH_SCC_PASS_H -#include "llvm/Pass.h" #include "llvm/Analysis/CallGraph.h" +#include "llvm/Pass.h" namespace llvm { @@ -39,6 +39,9 @@ public: /// corresponding to a CallGraph. Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + using llvm::Pass::doInitialization; + using llvm::Pass::doFinalization; + /// doInitialization - This method is called before the SCC's of the program /// has been processed, allowing the pass to do initialization as necessary. virtual bool doInitialization(CallGraph &CG) { diff --git a/include/llvm/Analysis/CaptureTracking.h b/include/llvm/Analysis/CaptureTracking.h index 9b5e842..5e2a5ec 100644 --- a/include/llvm/Analysis/CaptureTracking.h +++ b/include/llvm/Analysis/CaptureTracking.h @@ -14,9 +14,9 @@ #ifndef LLVM_ANALYSIS_CAPTURETRACKING_H #define LLVM_ANALYSIS_CAPTURETRACKING_H -#include "llvm/Constants.h" -#include "llvm/Instructions.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/CallSite.h" namespace llvm { @@ -46,7 +46,7 @@ namespace llvm { /// capture) return false. To search it, return true. /// /// U->getUser() is always an Instruction. - virtual bool shouldExplore(Use *U) = 0; + virtual bool shouldExplore(Use *U); /// captured - Information about the pointer was captured by the user of /// use U. Return true to stop the traversal or false to continue looking diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 03c807c..35eabec 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -22,11 +22,11 @@ namespace llvm { class BasicBlock; class Function; class Instruction; - class TargetData; + class DataLayout; class Value; /// \brief Check whether an instruction is likely to be "free" when lowered. - bool isInstructionFree(const Instruction *I, const TargetData *TD = 0); + bool isInstructionFree(const Instruction *I, const DataLayout *TD = 0); /// \brief Check whether a call will lower to something small. /// @@ -46,8 +46,11 @@ namespace llvm { /// \brief True if this function calls itself. bool isRecursive; - /// \brief True if this function contains one or more indirect branches. - bool containsIndirectBr; + /// \brief True if this function cannot be duplicated. + /// + /// True if this function contains one or more indirect branches, or it contains + /// one or more 'noduplicate' instructions. + bool notDuplicatable; /// \brief True if this function calls alloca (in the C sense). bool usesDynamicAlloca; @@ -79,16 +82,16 @@ namespace llvm { unsigned NumRets; CodeMetrics() : exposesReturnsTwice(false), isRecursive(false), - containsIndirectBr(false), usesDynamicAlloca(false), + notDuplicatable(false), usesDynamicAlloca(false), NumInsts(0), NumBlocks(0), NumCalls(0), NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {} /// \brief Add information about a block to the current state. - void analyzeBasicBlock(const BasicBlock *BB, const TargetData *TD = 0); + void analyzeBasicBlock(const BasicBlock *BB, const DataLayout *TD = 0); /// \brief Add information about a function to the current state. - void analyzeFunction(Function *F, const TargetData *TD = 0); + void analyzeFunction(Function *F, const DataLayout *TD = 0); }; } diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 2fdef5f..12e623e 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -12,7 +12,7 @@ // // Also, to supplement the basic VMCore ConstantExpr simplifications, // this file declares some additional folding routines that can make use of -// TargetData information. These functions cannot go in VMCore due to library +// DataLayout information. These functions cannot go in VMCore due to library // dependency issues. // //===----------------------------------------------------------------------===// @@ -24,7 +24,7 @@ namespace llvm { class Constant; class ConstantExpr; class Instruction; - class TargetData; + class DataLayout; class TargetLibraryInfo; class Function; class Type; @@ -36,14 +36,14 @@ namespace llvm { /// Note that this fails if not all of the operands are constant. Otherwise, /// this function can only fail when attempting to fold instructions like loads /// and stores, which have no constant expression form. -Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0, +Constant *ConstantFoldInstruction(Instruction *I, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0); /// ConstantFoldConstantExpression - Attempt to fold the constant expression -/// using the specified TargetData. If successful, the constant result is +/// using the specified DataLayout. If successful, the constant result is /// result is returned, if not, null is returned. Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0); /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the @@ -54,7 +54,7 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, /// Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, ArrayRef<Constant *> Ops, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0); /// ConstantFoldCompareInstOperands - Attempt to constant fold a compare @@ -63,7 +63,7 @@ Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, /// Constant *ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0); /// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue @@ -75,7 +75,7 @@ Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// produce if it is constant and determinable. If this is not determinable, /// return null. -Constant *ConstantFoldLoadFromConstPtr(Constant *C, const TargetData *TD = 0); +Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout *TD = 0); /// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a /// getelementptr constantexpr, return the constant value being addressed by the diff --git a/include/llvm/Analysis/DOTGraphTraitsPass.h b/include/llvm/Analysis/DOTGraphTraitsPass.h index b701b8f..bd8c4a1 100644 --- a/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -14,8 +14,8 @@ #ifndef LLVM_ANALYSIS_DOT_GRAPHTRAITS_PASS_H #define LLVM_ANALYSIS_DOT_GRAPHTRAITS_PASS_H -#include "llvm/Pass.h" #include "llvm/Analysis/CFGPrinter.h" +#include "llvm/Pass.h" namespace llvm { template <class Analysis, bool Simple> diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h new file mode 100644 index 0000000..f49efd9 --- /dev/null +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -0,0 +1,895 @@ +//===-- llvm/Analysis/DependenceAnalysis.h -------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// DependenceAnalysis is an LLVM pass that analyses dependences between memory +// accesses. Currently, it is an implementation of the approach described in +// +// Practical Dependence Testing +// Goff, Kennedy, Tseng +// PLDI 1991 +// +// There's a single entry point that analyzes the dependence between a pair +// of memory references in a function, returning either NULL, for no dependence, +// or a more-or-less detailed description of the dependence between them. +// +// This pass exists to support the DependenceGraph pass. There are two separate +// passes because there's a useful separation of concerns. A dependence exists +// if two conditions are met: +// +// 1) Two instructions reference the same memory location, and +// 2) There is a flow of control leading from one instruction to the other. +// +// DependenceAnalysis attacks the first condition; DependenceGraph will attack +// the second (it's not yet ready). +// +// Please note that this is work in progress and the interface is subject to +// change. +// +// Plausible changes: +// Return a set of more precise dependences instead of just one dependence +// summarizing all. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DEPENDENCEANALYSIS_H +#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H + +#include "llvm/ADT/SmallBitVector.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Pass.h" + +namespace llvm { + class AliasAnalysis; + class Loop; + class LoopInfo; + class ScalarEvolution; + class SCEV; + class SCEVConstant; + class raw_ostream; + + /// Dependence - This class represents a dependence between two memory + /// memory references in a function. It contains minimal information and + /// is used in the very common situation where the compiler is unable to + /// determine anything beyond the existence of a dependence; that is, it + /// represents a confused dependence (see also FullDependence). In most + /// cases (for output, flow, and anti dependences), the dependence implies + /// an ordering, where the source must precede the destination; in contrast, + /// input dependences are unordered. + class Dependence { + public: + Dependence(Instruction *Source, + Instruction *Destination) : + Src(Source), Dst(Destination) {} + virtual ~Dependence() {} + + /// Dependence::DVEntry - Each level in the distance/direction vector + /// has a direction (or perhaps a union of several directions), and + /// perhaps a distance. + struct DVEntry { + enum { NONE = 0, + LT = 1, + EQ = 2, + LE = 3, + GT = 4, + NE = 5, + GE = 6, + ALL = 7 }; + unsigned char Direction : 3; // Init to ALL, then refine. + bool Scalar : 1; // Init to true. + bool PeelFirst : 1; // Peeling the first iteration will break dependence. + bool PeelLast : 1; // Peeling the last iteration will break the dependence. + bool Splitable : 1; // Splitting the loop will break dependence. + const SCEV *Distance; // NULL implies no distance available. + DVEntry() : Direction(ALL), Scalar(true), PeelFirst(false), + PeelLast(false), Splitable(false), Distance(NULL) { } + }; + + /// getSrc - Returns the source instruction for this dependence. + /// + Instruction *getSrc() const { return Src; } + + /// getDst - Returns the destination instruction for this dependence. + /// + Instruction *getDst() const { return Dst; } + + /// isInput - Returns true if this is an input dependence. + /// + bool isInput() const; + + /// isOutput - Returns true if this is an output dependence. + /// + bool isOutput() const; + + /// isFlow - Returns true if this is a flow (aka true) dependence. + /// + bool isFlow() const; + + /// isAnti - Returns true if this is an anti dependence. + /// + bool isAnti() const; + + /// isOrdered - Returns true if dependence is Output, Flow, or Anti + /// + bool isOrdered() const { return isOutput() || isFlow() || isAnti(); } + + /// isUnordered - Returns true if dependence is Input + /// + bool isUnordered() const { return isInput(); } + + /// isLoopIndependent - Returns true if this is a loop-independent + /// dependence. + virtual bool isLoopIndependent() const { return true; } + + /// isConfused - Returns true if this dependence is confused + /// (the compiler understands nothing and makes worst-case + /// assumptions). + virtual bool isConfused() const { return true; } + + /// isConsistent - Returns true if this dependence is consistent + /// (occurs every time the source and destination are executed). + virtual bool isConsistent() const { return false; } + + /// getLevels - Returns the number of common loops surrounding the + /// source and destination of the dependence. + virtual unsigned getLevels() const { return 0; } + + /// getDirection - Returns the direction associated with a particular + /// level. + virtual unsigned getDirection(unsigned Level) const { return DVEntry::ALL; } + + /// getDistance - Returns the distance (or NULL) associated with a + /// particular level. + virtual const SCEV *getDistance(unsigned Level) const { return NULL; } + + /// isPeelFirst - Returns true if peeling the first iteration from + /// this loop will break this dependence. + virtual bool isPeelFirst(unsigned Level) const { return false; } + + /// isPeelLast - Returns true if peeling the last iteration from + /// this loop will break this dependence. + virtual bool isPeelLast(unsigned Level) const { return false; } + + /// isSplitable - Returns true if splitting this loop will break + /// the dependence. + virtual bool isSplitable(unsigned Level) const { return false; } + + /// isScalar - Returns true if a particular level is scalar; that is, + /// if no subscript in the source or destination mention the induction + /// variable associated with the loop at this level. + virtual bool isScalar(unsigned Level) const; + + /// dump - For debugging purposes, dumps a dependence to OS. + /// + void dump(raw_ostream &OS) const; + private: + Instruction *Src, *Dst; + friend class DependenceAnalysis; + }; + + + /// FullDependence - This class represents a dependence between two memory + /// references in a function. It contains detailed information about the + /// dependence (direction vectors, etc) and is used when the compiler is + /// able to accurately analyze the interaction of the references; that is, + /// it is not a confused dependence (see Dependence). In most cases + /// (for output, flow, and anti dependences), the dependence implies an + /// ordering, where the source must precede the destination; in contrast, + /// input dependences are unordered. + class FullDependence : public Dependence { + public: + FullDependence(Instruction *Src, + Instruction *Dst, + bool LoopIndependent, + unsigned Levels); + ~FullDependence() { + delete[] DV; + } + + /// isLoopIndependent - Returns true if this is a loop-independent + /// dependence. + bool isLoopIndependent() const { return LoopIndependent; } + + /// isConfused - Returns true if this dependence is confused + /// (the compiler understands nothing and makes worst-case + /// assumptions). + bool isConfused() const { return false; } + + /// isConsistent - Returns true if this dependence is consistent + /// (occurs every time the source and destination are executed). + bool isConsistent() const { return Consistent; } + + /// getLevels - Returns the number of common loops surrounding the + /// source and destination of the dependence. + unsigned getLevels() const { return Levels; } + + /// getDirection - Returns the direction associated with a particular + /// level. + unsigned getDirection(unsigned Level) const; + + /// getDistance - Returns the distance (or NULL) associated with a + /// particular level. + const SCEV *getDistance(unsigned Level) const; + + /// isPeelFirst - Returns true if peeling the first iteration from + /// this loop will break this dependence. + bool isPeelFirst(unsigned Level) const; + + /// isPeelLast - Returns true if peeling the last iteration from + /// this loop will break this dependence. + bool isPeelLast(unsigned Level) const; + + /// isSplitable - Returns true if splitting the loop will break + /// the dependence. + bool isSplitable(unsigned Level) const; + + /// isScalar - Returns true if a particular level is scalar; that is, + /// if no subscript in the source or destination mention the induction + /// variable associated with the loop at this level. + bool isScalar(unsigned Level) const; + private: + unsigned short Levels; + bool LoopIndependent; + bool Consistent; // Init to true, then refine. + DVEntry *DV; + friend class DependenceAnalysis; + }; + + + /// DependenceAnalysis - This class is the main dependence-analysis driver. + /// + class DependenceAnalysis : public FunctionPass { + void operator=(const DependenceAnalysis &); // do not implement + DependenceAnalysis(const DependenceAnalysis &); // do not implement + public: + /// depends - Tests for a dependence between the Src and Dst instructions. + /// Returns NULL if no dependence; otherwise, returns a Dependence (or a + /// FullDependence) with as much information as can be gleaned. + /// The flag PossiblyLoopIndependent should be set by the caller + /// if it appears that control flow can reach from Src to Dst + /// without traversing a loop back edge. + Dependence *depends(Instruction *Src, + Instruction *Dst, + bool PossiblyLoopIndependent); + + /// getSplitIteration - Give a dependence that's splitable at some + /// particular level, return the iteration that should be used to split + /// the loop. + /// + /// Generally, the dependence analyzer will be used to build + /// a dependence graph for a function (basically a map from instructions + /// to dependences). Looking for cycles in the graph shows us loops + /// that cannot be trivially vectorized/parallelized. + /// + /// We can try to improve the situation by examining all the dependences + /// that make up the cycle, looking for ones we can break. + /// Sometimes, peeling the first or last iteration of a loop will break + /// dependences, and there are flags for those possibilities. + /// Sometimes, splitting a loop at some other iteration will do the trick, + /// and we've got a flag for that case. Rather than waste the space to + /// record the exact iteration (since we rarely know), we provide + /// a method that calculates the iteration. It's a drag that it must work + /// from scratch, but wonderful in that it's possible. + /// + /// Here's an example: + /// + /// for (i = 0; i < 10; i++) + /// A[i] = ... + /// ... = A[11 - i] + /// + /// There's a loop-carried flow dependence from the store to the load, + /// found by the weak-crossing SIV test. The dependence will have a flag, + /// indicating that the dependence can be broken by splitting the loop. + /// Calling getSplitIteration will return 5. + /// Splitting the loop breaks the dependence, like so: + /// + /// for (i = 0; i <= 5; i++) + /// A[i] = ... + /// ... = A[11 - i] + /// for (i = 6; i < 10; i++) + /// A[i] = ... + /// ... = A[11 - i] + /// + /// breaks the dependence and allows us to vectorize/parallelize + /// both loops. + const SCEV *getSplitIteration(const Dependence *Dep, unsigned Level); + + private: + AliasAnalysis *AA; + ScalarEvolution *SE; + LoopInfo *LI; + Function *F; + + /// Subscript - This private struct represents a pair of subscripts from + /// a pair of potentially multi-dimensional array references. We use a + /// vector of them to guide subscript partitioning. + struct Subscript { + const SCEV *Src; + const SCEV *Dst; + enum ClassificationKind { ZIV, SIV, RDIV, MIV, NonLinear } Classification; + SmallBitVector Loops; + SmallBitVector GroupLoops; + SmallBitVector Group; + }; + + struct CoefficientInfo { + const SCEV *Coeff; + const SCEV *PosPart; + const SCEV *NegPart; + const SCEV *Iterations; + }; + + struct BoundInfo { + const SCEV *Iterations; + const SCEV *Upper[8]; + const SCEV *Lower[8]; + unsigned char Direction; + unsigned char DirSet; + }; + + /// Constraint - This private class represents a constraint, as defined + /// in the paper + /// + /// Practical Dependence Testing + /// Goff, Kennedy, Tseng + /// PLDI 1991 + /// + /// There are 5 kinds of constraint, in a hierarchy. + /// 1) Any - indicates no constraint, any dependence is possible. + /// 2) Line - A line ax + by = c, where a, b, and c are parameters, + /// representing the dependence equation. + /// 3) Distance - The value d of the dependence distance; + /// 4) Point - A point <x, y> representing the dependence from + /// iteration x to iteration y. + /// 5) Empty - No dependence is possible. + class Constraint { + private: + enum ConstraintKind { Empty, Point, Distance, Line, Any } Kind; + ScalarEvolution *SE; + const SCEV *A; + const SCEV *B; + const SCEV *C; + const Loop *AssociatedLoop; + public: + /// isEmpty - Return true if the constraint is of kind Empty. + bool isEmpty() const { return Kind == Empty; } + + /// isPoint - Return true if the constraint is of kind Point. + bool isPoint() const { return Kind == Point; } + + /// isDistance - Return true if the constraint is of kind Distance. + bool isDistance() const { return Kind == Distance; } + + /// isLine - Return true if the constraint is of kind Line. + /// Since Distance's can also be represented as Lines, we also return + /// true if the constraint is of kind Distance. + bool isLine() const { return Kind == Line || Kind == Distance; } + + /// isAny - Return true if the constraint is of kind Any; + bool isAny() const { return Kind == Any; } + + /// getX - If constraint is a point <X, Y>, returns X. + /// Otherwise assert. + const SCEV *getX() const; + + /// getY - If constraint is a point <X, Y>, returns Y. + /// Otherwise assert. + const SCEV *getY() const; + + /// getA - If constraint is a line AX + BY = C, returns A. + /// Otherwise assert. + const SCEV *getA() const; + + /// getB - If constraint is a line AX + BY = C, returns B. + /// Otherwise assert. + const SCEV *getB() const; + + /// getC - If constraint is a line AX + BY = C, returns C. + /// Otherwise assert. + const SCEV *getC() const; + + /// getD - If constraint is a distance, returns D. + /// Otherwise assert. + const SCEV *getD() const; + + /// getAssociatedLoop - Returns the loop associated with this constraint. + const Loop *getAssociatedLoop() const; + + /// setPoint - Change a constraint to Point. + void setPoint(const SCEV *X, const SCEV *Y, const Loop *CurrentLoop); + + /// setLine - Change a constraint to Line. + void setLine(const SCEV *A, const SCEV *B, + const SCEV *C, const Loop *CurrentLoop); + + /// setDistance - Change a constraint to Distance. + void setDistance(const SCEV *D, const Loop *CurrentLoop); + + /// setEmpty - Change a constraint to Empty. + void setEmpty(); + + /// setAny - Change a constraint to Any. + void setAny(ScalarEvolution *SE); + + /// dump - For debugging purposes. Dumps the constraint + /// out to OS. + void dump(raw_ostream &OS) const; + }; + + + /// establishNestingLevels - Examines the loop nesting of the Src and Dst + /// instructions and establishes their shared loops. Sets the variables + /// CommonLevels, SrcLevels, and MaxLevels. + /// The source and destination instructions needn't be contained in the same + /// loop. The routine establishNestingLevels finds the level of most deeply + /// nested loop that contains them both, CommonLevels. An instruction that's + /// not contained in a loop is at level = 0. MaxLevels is equal to the level + /// of the source plus the level of the destination, minus CommonLevels. + /// This lets us allocate vectors MaxLevels in length, with room for every + /// distinct loop referenced in both the source and destination subscripts. + /// The variable SrcLevels is the nesting depth of the source instruction. + /// It's used to help calculate distinct loops referenced by the destination. + /// Here's the map from loops to levels: + /// 0 - unused + /// 1 - outermost common loop + /// ... - other common loops + /// CommonLevels - innermost common loop + /// ... - loops containing Src but not Dst + /// SrcLevels - innermost loop containing Src but not Dst + /// ... - loops containing Dst but not Src + /// MaxLevels - innermost loop containing Dst but not Src + /// Consider the follow code fragment: + /// for (a = ...) { + /// for (b = ...) { + /// for (c = ...) { + /// for (d = ...) { + /// A[] = ...; + /// } + /// } + /// for (e = ...) { + /// for (f = ...) { + /// for (g = ...) { + /// ... = A[]; + /// } + /// } + /// } + /// } + /// } + /// If we're looking at the possibility of a dependence between the store + /// to A (the Src) and the load from A (the Dst), we'll note that they + /// have 2 loops in common, so CommonLevels will equal 2 and the direction + /// vector for Result will have 2 entries. SrcLevels = 4 and MaxLevels = 7. + /// A map from loop names to level indices would look like + /// a - 1 + /// b - 2 = CommonLevels + /// c - 3 + /// d - 4 = SrcLevels + /// e - 5 + /// f - 6 + /// g - 7 = MaxLevels + void establishNestingLevels(const Instruction *Src, + const Instruction *Dst); + + unsigned CommonLevels, SrcLevels, MaxLevels; + + /// mapSrcLoop - Given one of the loops containing the source, return + /// its level index in our numbering scheme. + unsigned mapSrcLoop(const Loop *SrcLoop) const; + + /// mapDstLoop - Given one of the loops containing the destination, + /// return its level index in our numbering scheme. + unsigned mapDstLoop(const Loop *DstLoop) const; + + /// isLoopInvariant - Returns true if Expression is loop invariant + /// in LoopNest. + bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const; + + /// removeMatchingExtensions - Examines a subscript pair. + /// If the source and destination are identically sign (or zero) + /// extended, it strips off the extension in an effort to + /// simplify the actual analysis. + void removeMatchingExtensions(Subscript *Pair); + + /// collectCommonLoops - Finds the set of loops from the LoopNest that + /// have a level <= CommonLevels and are referred to by the SCEV Expression. + void collectCommonLoops(const SCEV *Expression, + const Loop *LoopNest, + SmallBitVector &Loops) const; + + /// checkSrcSubscript - Examines the SCEV Src, returning true iff it's + /// linear. Collect the set of loops mentioned by Src. + bool checkSrcSubscript(const SCEV *Src, + const Loop *LoopNest, + SmallBitVector &Loops); + + /// checkDstSubscript - Examines the SCEV Dst, returning true iff it's + /// linear. Collect the set of loops mentioned by Dst. + bool checkDstSubscript(const SCEV *Dst, + const Loop *LoopNest, + SmallBitVector &Loops); + + /// isKnownPredicate - Compare X and Y using the predicate Pred. + /// Basically a wrapper for SCEV::isKnownPredicate, + /// but tries harder, especially in the presence of sign and zero + /// extensions and symbolics. + bool isKnownPredicate(ICmpInst::Predicate Pred, + const SCEV *X, + const SCEV *Y) const; + + /// collectUpperBound - All subscripts are the same type (on my machine, + /// an i64). The loop bound may be a smaller type. collectUpperBound + /// find the bound, if available, and zero extends it to the Type T. + /// (I zero extend since the bound should always be >= 0.) + /// If no upper bound is available, return NULL. + const SCEV *collectUpperBound(const Loop *l, Type *T) const; + + /// collectConstantUpperBound - Calls collectUpperBound(), then + /// attempts to cast it to SCEVConstant. If the cast fails, + /// returns NULL. + const SCEVConstant *collectConstantUpperBound(const Loop *l, Type *T) const; + + /// classifyPair - Examines the subscript pair (the Src and Dst SCEVs) + /// and classifies it as either ZIV, SIV, RDIV, MIV, or Nonlinear. + /// Collects the associated loops in a set. + Subscript::ClassificationKind classifyPair(const SCEV *Src, + const Loop *SrcLoopNest, + const SCEV *Dst, + const Loop *DstLoopNest, + SmallBitVector &Loops); + + /// testZIV - Tests the ZIV subscript pair (Src and Dst) for dependence. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// If the dependence isn't proven to exist, + /// marks the Result as inconsistent. + bool testZIV(const SCEV *Src, + const SCEV *Dst, + FullDependence &Result) const; + + /// testSIV - Tests the SIV subscript pair (Src and Dst) for dependence. + /// Things of the form [c1 + a1*i] and [c2 + a2*j], where + /// i and j are induction variables, c1 and c2 are loop invariant, + /// and a1 and a2 are constant. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction vector entry and, when possible, + /// the distance vector entry. + /// If the dependence isn't proven to exist, + /// marks the Result as inconsistent. + bool testSIV(const SCEV *Src, + const SCEV *Dst, + unsigned &Level, + FullDependence &Result, + Constraint &NewConstraint, + const SCEV *&SplitIter) const; + + /// testRDIV - Tests the RDIV subscript pair (Src and Dst) for dependence. + /// Things of the form [c1 + a1*i] and [c2 + a2*j] + /// where i and j are induction variables, c1 and c2 are loop invariant, + /// and a1 and a2 are constant. + /// With minor algebra, this test can also be used for things like + /// [c1 + a1*i + a2*j][c2]. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Marks the Result as inconsistent. + bool testRDIV(const SCEV *Src, + const SCEV *Dst, + FullDependence &Result) const; + + /// testMIV - Tests the MIV subscript pair (Src and Dst) for dependence. + /// Returns true if dependence disproved. + /// Can sometimes refine direction vectors. + bool testMIV(const SCEV *Src, + const SCEV *Dst, + const SmallBitVector &Loops, + FullDependence &Result) const; + + /// strongSIVtest - Tests the strong SIV subscript pair (Src and Dst) + /// for dependence. + /// Things of the form [c1 + a*i] and [c2 + a*i], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a is a constant + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction and distance. + bool strongSIVtest(const SCEV *Coeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint) const; + + /// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair + /// (Src and Dst) for dependence. + /// Things of the form [c1 + a*i] and [c2 - a*i], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a is a constant. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction entry. + /// Set consistent to false. + /// Marks the dependence as splitable. + bool weakCrossingSIVtest(const SCEV *SrcCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint, + const SCEV *&SplitIter) const; + + /// ExactSIVtest - Tests the SIV subscript pair + /// (Src and Dst) for dependence. + /// Things of the form [c1 + a1*i] and [c2 + a2*i], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a1 and a2 are constant. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction entry. + /// Set consistent to false. + bool exactSIVtest(const SCEV *SrcCoeff, + const SCEV *DstCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint) const; + + /// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair + /// (Src and Dst) for dependence. + /// Things of the form [c1] and [c2 + a*i], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a is a constant. See also weakZeroDstSIVtest. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction entry. + /// Set consistent to false. + /// If loop peeling will break the dependence, mark appropriately. + bool weakZeroSrcSIVtest(const SCEV *DstCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint) const; + + /// weakZeroDstSIVtest - Tests the weak-zero SIV subscript pair + /// (Src and Dst) for dependence. + /// Things of the form [c1 + a*i] and [c2], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a is a constant. See also weakZeroSrcSIVtest. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction entry. + /// Set consistent to false. + /// If loop peeling will break the dependence, mark appropriately. + bool weakZeroDstSIVtest(const SCEV *SrcCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint) const; + + /// exactRDIVtest - Tests the RDIV subscript pair for dependence. + /// Things of the form [c1 + a*i] and [c2 + b*j], + /// where i and j are induction variable, c1 and c2 are loop invariant, + /// and a and b are constants. + /// Returns true if any possible dependence is disproved. + /// Marks the result as inconsistent. + /// Works in some cases that symbolicRDIVtest doesn't, + /// and vice versa. + bool exactRDIVtest(const SCEV *SrcCoeff, + const SCEV *DstCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *SrcLoop, + const Loop *DstLoop, + FullDependence &Result) const; + + /// symbolicRDIVtest - Tests the RDIV subscript pair for dependence. + /// Things of the form [c1 + a*i] and [c2 + b*j], + /// where i and j are induction variable, c1 and c2 are loop invariant, + /// and a and b are constants. + /// Returns true if any possible dependence is disproved. + /// Marks the result as inconsistent. + /// Works in some cases that exactRDIVtest doesn't, + /// and vice versa. Can also be used as a backup for + /// ordinary SIV tests. + bool symbolicRDIVtest(const SCEV *SrcCoeff, + const SCEV *DstCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *SrcLoop, + const Loop *DstLoop) const; + + /// gcdMIVtest - Tests an MIV subscript pair for dependence. + /// Returns true if any possible dependence is disproved. + /// Marks the result as inconsistent. + /// Can sometimes disprove the equal direction for 1 or more loops. + // Can handle some symbolics that even the SIV tests don't get, + /// so we use it as a backup for everything. + bool gcdMIVtest(const SCEV *Src, + const SCEV *Dst, + FullDependence &Result) const; + + /// banerjeeMIVtest - Tests an MIV subscript pair for dependence. + /// Returns true if any possible dependence is disproved. + /// Marks the result as inconsistent. + /// Computes directions. + bool banerjeeMIVtest(const SCEV *Src, + const SCEV *Dst, + const SmallBitVector &Loops, + FullDependence &Result) const; + + /// collectCoefficientInfo - Walks through the subscript, + /// collecting each coefficient, the associated loop bounds, + /// and recording its positive and negative parts for later use. + CoefficientInfo *collectCoeffInfo(const SCEV *Subscript, + bool SrcFlag, + const SCEV *&Constant) const; + + /// getPositivePart - X^+ = max(X, 0). + /// + const SCEV *getPositivePart(const SCEV *X) const; + + /// getNegativePart - X^- = min(X, 0). + /// + const SCEV *getNegativePart(const SCEV *X) const; + + /// getLowerBound - Looks through all the bounds info and + /// computes the lower bound given the current direction settings + /// at each level. + const SCEV *getLowerBound(BoundInfo *Bound) const; + + /// getUpperBound - Looks through all the bounds info and + /// computes the upper bound given the current direction settings + /// at each level. + const SCEV *getUpperBound(BoundInfo *Bound) const; + + /// exploreDirections - Hierarchically expands the direction vector + /// search space, combining the directions of discovered dependences + /// in the DirSet field of Bound. Returns the number of distinct + /// dependences discovered. If the dependence is disproved, + /// it will return 0. + unsigned exploreDirections(unsigned Level, + CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + const SmallBitVector &Loops, + unsigned &DepthExpanded, + const SCEV *Delta) const; + + /// testBounds - Returns true iff the current bounds are plausible. + /// + bool testBounds(unsigned char DirKind, + unsigned Level, + BoundInfo *Bound, + const SCEV *Delta) const; + + /// findBoundsALL - Computes the upper and lower bounds for level K + /// using the * direction. Records them in Bound. + void findBoundsALL(CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + unsigned K) const; + + /// findBoundsLT - Computes the upper and lower bounds for level K + /// using the < direction. Records them in Bound. + void findBoundsLT(CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + unsigned K) const; + + /// findBoundsGT - Computes the upper and lower bounds for level K + /// using the > direction. Records them in Bound. + void findBoundsGT(CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + unsigned K) const; + + /// findBoundsEQ - Computes the upper and lower bounds for level K + /// using the = direction. Records them in Bound. + void findBoundsEQ(CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + unsigned K) const; + + /// intersectConstraints - Updates X with the intersection + /// of the Constraints X and Y. Returns true if X has changed. + bool intersectConstraints(Constraint *X, + const Constraint *Y); + + /// propagate - Review the constraints, looking for opportunities + /// to simplify a subscript pair (Src and Dst). + /// Return true if some simplification occurs. + /// If the simplification isn't exact (that is, if it is conservative + /// in terms of dependence), set consistent to false. + bool propagate(const SCEV *&Src, + const SCEV *&Dst, + SmallBitVector &Loops, + SmallVector<Constraint, 4> &Constraints, + bool &Consistent); + + /// propagateDistance - Attempt to propagate a distance + /// constraint into a subscript pair (Src and Dst). + /// Return true if some simplification occurs. + /// If the simplification isn't exact (that is, if it is conservative + /// in terms of dependence), set consistent to false. + bool propagateDistance(const SCEV *&Src, + const SCEV *&Dst, + Constraint &CurConstraint, + bool &Consistent); + + /// propagatePoint - Attempt to propagate a point + /// constraint into a subscript pair (Src and Dst). + /// Return true if some simplification occurs. + bool propagatePoint(const SCEV *&Src, + const SCEV *&Dst, + Constraint &CurConstraint); + + /// propagateLine - Attempt to propagate a line + /// constraint into a subscript pair (Src and Dst). + /// Return true if some simplification occurs. + /// If the simplification isn't exact (that is, if it is conservative + /// in terms of dependence), set consistent to false. + bool propagateLine(const SCEV *&Src, + const SCEV *&Dst, + Constraint &CurConstraint, + bool &Consistent); + + /// findCoefficient - Given a linear SCEV, + /// return the coefficient corresponding to specified loop. + /// If there isn't one, return the SCEV constant 0. + /// For example, given a*i + b*j + c*k, returning the coefficient + /// corresponding to the j loop would yield b. + const SCEV *findCoefficient(const SCEV *Expr, + const Loop *TargetLoop) const; + + /// zeroCoefficient - Given a linear SCEV, + /// return the SCEV given by zeroing out the coefficient + /// corresponding to the specified loop. + /// For example, given a*i + b*j + c*k, zeroing the coefficient + /// corresponding to the j loop would yield a*i + c*k. + const SCEV *zeroCoefficient(const SCEV *Expr, + const Loop *TargetLoop) const; + + /// addToCoefficient - Given a linear SCEV Expr, + /// return the SCEV given by adding some Value to the + /// coefficient corresponding to the specified TargetLoop. + /// For example, given a*i + b*j + c*k, adding 1 to the coefficient + /// corresponding to the j loop would yield a*i + (b+1)*j + c*k. + const SCEV *addToCoefficient(const SCEV *Expr, + const Loop *TargetLoop, + const SCEV *Value) const; + + /// updateDirection - Update direction vector entry + /// based on the current constraint. + void updateDirection(Dependence::DVEntry &Level, + const Constraint &CurConstraint) const; + public: + static char ID; // Class identification, replacement for typeinfo + DependenceAnalysis() : FunctionPass(ID) { + initializeDependenceAnalysisPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F); + void releaseMemory(); + void getAnalysisUsage(AnalysisUsage &) const; + void print(raw_ostream &, const Module * = 0) const; + }; // class DependenceAnalysis + + /// createDependenceAnalysisPass - This creates an instance of the + /// DependenceAnalysis pass. + FunctionPass *createDependenceAnalysisPass(); + +} // namespace llvm + +#endif diff --git a/include/llvm/Analysis/DominatorInternals.h b/include/llvm/Analysis/DominatorInternals.h index 0c29236..c0f95cb 100644 --- a/include/llvm/Analysis/DominatorInternals.h +++ b/include/llvm/Analysis/DominatorInternals.h @@ -10,8 +10,8 @@ #ifndef LLVM_ANALYSIS_DOMINATOR_INTERNALS_H #define LLVM_ANALYSIS_DOMINATOR_INTERNALS_H -#include "llvm/Analysis/Dominators.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/Dominators.h" //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/Dominators.h b/include/llvm/Analysis/Dominators.h index a1cc196..d62a3ac 100644 --- a/include/llvm/Analysis/Dominators.h +++ b/include/llvm/Analysis/Dominators.h @@ -15,13 +15,13 @@ #ifndef LLVM_ANALYSIS_DOMINATORS_H #define LLVM_ANALYSIS_DOMINATORS_H -#include "llvm/Pass.h" -#include "llvm/Function.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Function.h" +#include "llvm/Pass.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" @@ -346,7 +346,7 @@ public: DomTreeNodeBase<NodeT> *getRootNode() { return RootNode; } const DomTreeNodeBase<NodeT> *getRootNode() const { return RootNode; } - /// properlyDominates - Returns true iff this dominates N and this != N. + /// properlyDominates - Returns true iff A dominates B and A != B. /// Note that this is not a constant time operation! /// bool properlyDominates(const DomTreeNodeBase<NodeT> *A, diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index 2bf79b9..9b98013 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -28,7 +28,7 @@ class IVUsers; class ScalarEvolution; class SCEV; class IVUsers; -class TargetData; +class DataLayout; /// IVStrideUse - Keep track of one use of a strided induction variable. /// The Expr member keeps track of the expression, User is the actual user @@ -123,7 +123,7 @@ class IVUsers : public LoopPass { LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; - TargetData *TD; + DataLayout *TD; SmallPtrSet<Instruction*,16> Processed; /// IVUses - A list of all tracked IV uses of induction variable expressions diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index 0cba135..42e329e 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -14,11 +14,11 @@ #ifndef LLVM_ANALYSIS_INLINECOST_H #define LLVM_ANALYSIS_INLINECOST_H -#include "llvm/Function.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/ValueMap.h" #include "llvm/Analysis/CodeMetrics.h" +#include "llvm/IR/Function.h" #include <cassert> #include <climits> #include <vector> @@ -26,7 +26,7 @@ namespace llvm { class CallSite; - class TargetData; + class DataLayout; namespace InlineConstants { // Various magic constants used to adjust heuristics. @@ -36,6 +36,9 @@ namespace llvm { const int LastCallToStaticBonus = -15000; const int ColdccPenalty = 2000; const int NoreturnPenalty = 10000; + /// Do not inline functions which allocate this many bytes on the stack + /// when the caller is recursive. + const unsigned TotalAllocaSizeRecursiveCaller = 1024; } /// \brief Represents the cost of inlining a function. @@ -101,13 +104,13 @@ namespace llvm { /// InlineCostAnalyzer - Cost analyzer used by inliner. class InlineCostAnalyzer { - // TargetData if available, or null. - const TargetData *TD; + // DataLayout if available, or null. + const DataLayout *TD; public: InlineCostAnalyzer(): TD(0) {} - void setTargetData(const TargetData *TData) { TD = TData; } + void setDataLayout(const DataLayout *TData) { TD = TData; } /// \brief Get an InlineCost object representing the cost of inlining this /// callsite. @@ -117,15 +120,18 @@ namespace llvm { /// bound the computation necessary to determine whether the cost is /// sufficiently low to warrant inlining. InlineCost getInlineCost(CallSite CS, int Threshold); - /// getCalledFunction - The heuristic used to determine if we should inline - /// the function call or not. The callee is explicitly specified, to allow - /// you to calculate the cost of inlining a function via a pointer. This - /// behaves exactly as the version with no explicit callee parameter in all - /// other respects. + + /// \brief Get an InlineCost with the callee explicitly specified. + /// This allows you to calculate the cost of inlining a function via a + /// pointer. This behaves exactly as the version with no explicit callee + /// parameter in all other respects. // // Note: This is used by out-of-tree passes, please do not remove without // adding a replacement API. InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold); + + /// \brief Minimal filter to detect invalid constructs for inlining. + bool isInlineViable(Function &Callee); }; } diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 152e885..b653e79 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -19,12 +19,15 @@ #ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H #define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H +#include "llvm/IR/User.h" + namespace llvm { template<typename T> class ArrayRef; class DominatorTree; class Instruction; - class TargetData; + class DataLayout; + class FastMathFlags; class TargetLibraryInfo; class Type; class Value; @@ -32,122 +35,144 @@ namespace llvm { /// SimplifyAddInst - Given operands for an Add, see if we can /// fold the result. If not, this returns null. Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifySubInst - Given operands for a Sub, see if we can /// fold the result. If not, this returns null. Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, - const TargetData *TD = 0, + const DataLayout *TD = 0, + const TargetLibraryInfo *TLI = 0, + const DominatorTree *DT = 0); + + /// Given operands for an FAdd, see if we can fold the result. If not, this + /// returns null. + Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const DataLayout *TD = 0, + const TargetLibraryInfo *TLI = 0, + const DominatorTree *DT = 0); + + /// Given operands for an FSub, see if we can fold the result. If not, this + /// returns null. + Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); + /// Given operands for an FMul, see if we can fold the result. If not, this + /// returns null. + Value *SimplifyFMulInst(Value *LHS, Value *RHS, + FastMathFlags FMF, + const DataLayout *TD = 0, + const TargetLibraryInfo *TLI = 0, + const DominatorTree *DT = 0); + /// SimplifyMulInst - Given operands for a Mul, see if we can /// fold the result. If not, this returns null. - Value *SimplifyMulInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifySDivInst - Given operands for an SDiv, see if we can /// fold the result. If not, this returns null. - Value *SimplifySDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyUDivInst - Given operands for a UDiv, see if we can /// fold the result. If not, this returns null. - Value *SimplifyUDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyFDivInst - Given operands for an FDiv, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifyFDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifySRemInst - Given operands for an SRem, see if we can /// fold the result. If not, this returns null. - Value *SimplifySRemInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyURemInst - Given operands for a URem, see if we can /// fold the result. If not, this returns null. - Value *SimplifyURemInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyFRemInst - Given operands for an FRem, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFRemInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifyFRemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyShlInst - Given operands for a Shl, see if we can /// fold the result. If not, this returns null. Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyLShrInst - Given operands for a LShr, see if we can /// fold the result. If not, this returns null. Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyAShrInst - Given operands for a AShr, see if we can /// fold the result. If not, this returns null. Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyAndInst - Given operands for an And, see if we can /// fold the result. If not, this returns null. - Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyOrInst - Given operands for an Or, see if we can /// fold the result. If not, this returns null. - Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyXorInst - Given operands for a Xor, see if we can /// fold the result. If not, this returns null. - Value *SimplifyXorInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold /// the result. If not, this returns null. Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. - Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const TargetData *TD = 0, + Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); @@ -155,13 +180,13 @@ namespace llvm { /// can fold the result. If not, this returns null. Value *SimplifyInsertValueInst(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold /// the result. If not, this returns null. - Value *SimplifyTruncInst(Value *Op, Type *Ty, const TargetData *TD = 0, + Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); @@ -171,20 +196,38 @@ namespace llvm { /// SimplifyCmpInst - Given operands for a CmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can /// fold the result. If not, this returns null. Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); + /// \brief Given a function and iterators over arguments, see if we can fold + /// the result. + /// + /// If this call could not be simplified returns null. + Value *SimplifyCall(Value *V, User::op_iterator ArgBegin, + User::op_iterator ArgEnd, const DataLayout *TD = 0, + const TargetLibraryInfo *TLI = 0, + const DominatorTree *DT = 0); + + /// \brief Given a function and set of arguments, see if we can fold the + /// result. + /// + /// If this call could not be simplified returns null. + Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, + const DataLayout *TD = 0, + const TargetLibraryInfo *TLI = 0, + const DominatorTree *DT = 0); + /// SimplifyInstruction - See if we can compute a simplified version of this /// instruction. If not, this returns null. - Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0, + Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); @@ -198,7 +241,7 @@ namespace llvm { /// /// The function returns true if any simplifications were performed. bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); @@ -209,7 +252,7 @@ namespace llvm { /// of the users impacted. It returns true if any simplifications were /// performed. bool recursivelySimplifyInstruction(Instruction *I, - const TargetData *TD = 0, + const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); } // end namespace llvm diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h index 0968c74..bd9ab20 100644 --- a/include/llvm/Analysis/IntervalIterator.h +++ b/include/llvm/Analysis/IntervalIterator.h @@ -34,7 +34,7 @@ #define LLVM_INTERVAL_ITERATOR_H #include "llvm/Analysis/IntervalPartition.h" -#include "llvm/Function.h" +#include "llvm/IR/Function.h" #include "llvm/Support/CFG.h" #include <algorithm> #include <set> diff --git a/include/llvm/Analysis/IntervalPartition.h b/include/llvm/Analysis/IntervalPartition.h index df7313f..bce84be 100644 --- a/include/llvm/Analysis/IntervalPartition.h +++ b/include/llvm/Analysis/IntervalPartition.h @@ -33,8 +33,8 @@ namespace llvm { // // IntervalPartition - This class builds and holds an "interval partition" for // a function. This partition divides the control flow graph into a set of -// maximal intervals, as defined with the properties above. Intuitively, a -// BasicBlock is a (possibly nonexistent) loop with a "tail" of non looping +// maximal intervals, as defined with the properties above. Intuitively, an +// interval is a (possibly nonexistent) loop with a "tail" of non looping // nodes following it. // class IntervalPartition : public FunctionPass { diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 065c230..197e94e 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -19,18 +19,18 @@ namespace llvm { class Constant; - class TargetData; + class DataLayout; class TargetLibraryInfo; class Value; /// LazyValueInfo - This pass computes, caches, and vends lazy value constraint /// information. class LazyValueInfo : public FunctionPass { - class TargetData *TD; + class DataLayout *TD; class TargetLibraryInfo *TLI; void *PImpl; - LazyValueInfo(const LazyValueInfo&); // DO NOT IMPLEMENT. - void operator=(const LazyValueInfo&); // DO NOT IMPLEMENT. + LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION; + void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION; public: static char ID; LazyValueInfo() : FunctionPass(ID), PImpl(0) { diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h index 5f0aefb..ebcb762 100644 --- a/include/llvm/Analysis/Loads.h +++ b/include/llvm/Analysis/Loads.h @@ -14,12 +14,12 @@ #ifndef LLVM_ANALYSIS_LOADS_H #define LLVM_ANALYSIS_LOADS_H -#include "llvm/BasicBlock.h" +#include "llvm/IR/BasicBlock.h" namespace llvm { class AliasAnalysis; -class TargetData; +class DataLayout; class MDNode; /// isSafeToLoadUnconditionally - Return true if we know that executing a load @@ -27,7 +27,7 @@ class MDNode; /// specified pointer, we do a quick local scan of the basic block containing /// ScanFrom, to determine if the address is already accessed. bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, - unsigned Align, const TargetData *TD = 0); + unsigned Align, const DataLayout *TD = 0); /// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at /// the instruction before ScanFrom) checking to see if we have the value at diff --git a/include/llvm/Analysis/LoopDependenceAnalysis.h b/include/llvm/Analysis/LoopDependenceAnalysis.h deleted file mode 100644 index f195d27..0000000 --- a/include/llvm/Analysis/LoopDependenceAnalysis.h +++ /dev/null @@ -1,124 +0,0 @@ -//===- llvm/Analysis/LoopDependenceAnalysis.h --------------- -*- C++ -*---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// LoopDependenceAnalysis is an LLVM pass that analyses dependences in memory -// accesses in loops. -// -// Please note that this is work in progress and the interface is subject to -// change. -// -// TODO: adapt as interface progresses -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H -#define LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/LoopPass.h" -#include "llvm/Support/Allocator.h" - -namespace llvm { - -class AliasAnalysis; -class AnalysisUsage; -class ScalarEvolution; -class SCEV; -class Value; -class raw_ostream; - -class LoopDependenceAnalysis : public LoopPass { - AliasAnalysis *AA; - ScalarEvolution *SE; - - /// L - The loop we are currently analysing. - Loop *L; - - /// TODO: doc - enum DependenceResult { Independent = 0, Dependent = 1, Unknown = 2 }; - - /// TODO: doc - struct Subscript { - /// TODO: Add distance, direction, breaking conditions, ... - }; - - /// DependencePair - Represents a data dependence relation between to memory - /// reference instructions. - struct DependencePair : public FastFoldingSetNode { - Value *A; - Value *B; - DependenceResult Result; - SmallVector<Subscript, 4> Subscripts; - - DependencePair(const FoldingSetNodeID &ID, Value *a, Value *b) : - FastFoldingSetNode(ID), A(a), B(b), Result(Unknown), Subscripts() {} - }; - - /// findOrInsertDependencePair - Return true if a DependencePair for the - /// given Values already exists, false if a new DependencePair had to be - /// created. The third argument is set to the pair found or created. - bool findOrInsertDependencePair(Value*, Value*, DependencePair*&); - - /// getLoops - Collect all loops of the loop nest L in which - /// a given SCEV is variant. - void getLoops(const SCEV*, DenseSet<const Loop*>*) const; - - /// isLoopInvariant - True if a given SCEV is invariant in all loops of the - /// loop nest starting at the innermost loop L. - bool isLoopInvariant(const SCEV*) const; - - /// isAffine - An SCEV is affine with respect to the loop nest starting at - /// the innermost loop L if it is of the form A+B*X where A, B are invariant - /// in the loop nest and X is a induction variable in the loop nest. - bool isAffine(const SCEV*) const; - - /// TODO: doc - bool isZIVPair(const SCEV*, const SCEV*) const; - bool isSIVPair(const SCEV*, const SCEV*) const; - DependenceResult analyseZIV(const SCEV*, const SCEV*, Subscript*) const; - DependenceResult analyseSIV(const SCEV*, const SCEV*, Subscript*) const; - DependenceResult analyseMIV(const SCEV*, const SCEV*, Subscript*) const; - DependenceResult analyseSubscript(const SCEV*, const SCEV*, Subscript*) const; - DependenceResult analysePair(DependencePair*) const; - -public: - static char ID; // Class identification, replacement for typeinfo - LoopDependenceAnalysis() : LoopPass(ID) { - initializeLoopDependenceAnalysisPass(*PassRegistry::getPassRegistry()); - } - - /// isDependencePair - Check whether two values can possibly give rise to - /// a data dependence: that is the case if both are instructions accessing - /// memory and at least one of those accesses is a write. - bool isDependencePair(const Value*, const Value*) const; - - /// depends - Return a boolean indicating if there is a data dependence - /// between two instructions. - bool depends(Value*, Value*); - - bool runOnLoop(Loop*, LPPassManager&); - virtual void releaseMemory(); - virtual void getAnalysisUsage(AnalysisUsage&) const; - void print(raw_ostream&, const Module* = 0) const; - -private: - FoldingSet<DependencePair> Pairs; - BumpPtrAllocator PairAllocator; -}; // class LoopDependenceAnalysis - -// createLoopDependenceAnalysisPass - This creates an instance of the -// LoopDependenceAnalysis pass. -// -LoopPass *createLoopDependenceAnalysisPass(); - -} // namespace llvm - -#endif /* LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H */ diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index eeb482d..830754d 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -30,14 +30,14 @@ #ifndef LLVM_ANALYSIS_LOOP_INFO_H #define LLVM_ANALYSIS_LOOP_INFO_H -#include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/Dominators.h" +#include "llvm/Pass.h" #include "llvm/Support/CFG.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -72,10 +72,9 @@ class LoopBase { // Blocks - The list of blocks in this loop. First entry is the header node. std::vector<BlockT*> Blocks; - // DO NOT IMPLEMENT - LoopBase(const LoopBase<BlockT, LoopT> &); - // DO NOT IMPLEMENT - const LoopBase<BlockT, LoopT>&operator=(const LoopBase<BlockT, LoopT> &); + LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; + const LoopBase<BlockT, LoopT>& + operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; public: /// Loop ctor - This creates an empty loop. LoopBase() : ParentLoop(0) {} @@ -416,8 +415,8 @@ class LoopInfoBase { friend class LoopBase<BlockT, LoopT>; friend class LoopInfo; - void operator=(const LoopInfoBase &); // do not implement - LoopInfoBase(const LoopInfo &); // do not implement + void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION; + LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION; public: LoopInfoBase() { } ~LoopInfoBase() { releaseMemory(); } @@ -550,8 +549,8 @@ class LoopInfo : public FunctionPass { LoopInfoBase<BasicBlock, Loop> LI; friend class LoopBase<BasicBlock, Loop>; - void operator=(const LoopInfo &); // do not implement - LoopInfo(const LoopInfo &); // do not implement + void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION; + LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION; public: static char ID; // Pass identification, replacement for typeid diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 3bb96f9..4b8e4c9 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -15,8 +15,8 @@ #ifndef LLVM_ANALYSIS_LOOP_INFO_IMPL_H #define LLVM_ANALYSIS_LOOP_INFO_IMPL_H -#include "llvm/Analysis/LoopInfo.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/Analysis/LoopInfo.h" namespace llvm { diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index e6ed9bc..f78472a 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -16,9 +16,9 @@ #define LLVM_LOOP_PASS_H #include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/Function.h" #include "llvm/Pass.h" #include "llvm/PassManagers.h" -#include "llvm/Function.h" #include <deque> namespace llvm { @@ -39,6 +39,9 @@ public: // whatever action is necessary for the specified Loop. virtual bool runOnLoop(Loop *L, LPPassManager &LPM) = 0; + using llvm::Pass::doInitialization; + using llvm::Pass::doFinalization; + // Initialization and finalization hooks. virtual bool doInitialization(Loop *L, LPPassManager &LPM) { return false; diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index c3ae603..f2c564f 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -15,19 +15,19 @@ #ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H #define LLVM_ANALYSIS_MEMORYBUILTINS_H -#include "llvm/IRBuilder.h" -#include "llvm/Operator.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Operator.h" +#include "llvm/InstVisitor.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/InstVisitor.h" #include "llvm/Support/TargetFolder.h" #include "llvm/Support/ValueHandle.h" namespace llvm { class CallInst; class PointerType; -class TargetData; +class DataLayout; class TargetLibraryInfo; class Type; class Value; @@ -81,7 +81,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 TargetData *TD, +const CallInst *isArrayMalloc(const Value *I, const DataLayout *TD, const TargetLibraryInfo *TLI); /// getMallocType - Returns the PointerType resulting from the malloc call. @@ -103,7 +103,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 TargetData *TD, +Value *getMallocArraySize(CallInst *CI, const DataLayout *TD, const TargetLibraryInfo *TLI, bool LookThroughSExt = false); @@ -141,7 +141,7 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { /// object size in Size if successful, and false otherwise. /// 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 TargetData *TD, +bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD, const TargetLibraryInfo *TLI, bool RoundToAlign = false); @@ -153,12 +153,12 @@ typedef std::pair<APInt, APInt> SizeOffsetType; class ObjectSizeOffsetVisitor : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { - const TargetData *TD; + const DataLayout *TD; const TargetLibraryInfo *TLI; bool RoundToAlign; unsigned IntTyBits; APInt Zero; - SmallPtrSet<Instruction *, 8> SeenInsts; + SmallPtrSet<Value*, 8> SeenInsts; APInt align(APInt Size, uint64_t Align); @@ -167,7 +167,7 @@ class ObjectSizeOffsetVisitor } public: - ObjectSizeOffsetVisitor(const TargetData *TD, const TargetLibraryInfo *TLI, + ObjectSizeOffsetVisitor(const DataLayout *TD, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign = false); SizeOffsetType compute(Value *V); @@ -191,6 +191,7 @@ public: SizeOffsetType visitExtractElementInst(ExtractElementInst &I); SizeOffsetType visitExtractValueInst(ExtractValueInst &I); SizeOffsetType visitGEPOperator(GEPOperator &GEP); + SizeOffsetType visitGlobalAlias(GlobalAlias &GA); SizeOffsetType visitGlobalVariable(GlobalVariable &GV); SizeOffsetType visitIntToPtrInst(IntToPtrInst&); SizeOffsetType visitLoadInst(LoadInst &I); @@ -213,7 +214,7 @@ class ObjectSizeOffsetEvaluator typedef DenseMap<const Value*, WeakEvalType> CacheMapTy; typedef SmallPtrSet<const Value*, 8> PtrSetTy; - const TargetData *TD; + const DataLayout *TD; const TargetLibraryInfo *TLI; LLVMContext &Context; BuilderTy Builder; @@ -228,7 +229,7 @@ class ObjectSizeOffsetEvaluator SizeOffsetEvalType compute_(Value *V); public: - ObjectSizeOffsetEvaluator(const TargetData *TD, const TargetLibraryInfo *TLI, + ObjectSizeOffsetEvaluator(const DataLayout *TD, const TargetLibraryInfo *TLI, LLVMContext &Context); SizeOffsetEvalType compute(Value *V); diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 7e049d6..b954840 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -14,14 +14,14 @@ #ifndef LLVM_ANALYSIS_MEMORY_DEPENDENCE_H #define LLVM_ANALYSIS_MEMORY_DEPENDENCE_H -#include "llvm/BasicBlock.h" -#include "llvm/Pass.h" -#include "llvm/Support/ValueHandle.h" -#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/Pass.h" +#include "llvm/Support/ValueHandle.h" namespace llvm { class Function; @@ -29,7 +29,7 @@ namespace llvm { class Instruction; class CallSite; class AliasAnalysis; - class TargetData; + class DataLayout; class MemoryDependenceAnalysis; class PredIteratorCache; class DominatorTree; @@ -323,7 +323,7 @@ namespace llvm { /// Current AA implementation, just a cache. AliasAnalysis *AA; - TargetData *TD; + DataLayout *TD; DominatorTree *DT; OwningPtr<PredIteratorCache> PredCache; public: @@ -412,7 +412,7 @@ namespace llvm { int64_t MemLocOffs, unsigned MemLocSize, const LoadInst *LI, - const TargetData &TD); + const DataLayout &TD); private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index ff9a247..d7a3dd8 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -14,12 +14,12 @@ #ifndef LLVM_ANALYSIS_PHITRANSADDR_H #define LLVM_ANALYSIS_PHITRANSADDR_H -#include "llvm/Instruction.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Instruction.h" namespace llvm { class DominatorTree; - class TargetData; + class DataLayout; class TargetLibraryInfo; /// PHITransAddr - An address value which tracks and handles phi translation. @@ -37,7 +37,7 @@ class PHITransAddr { Value *Addr; /// TD - The target data we are playing with if known, otherwise null. - const TargetData *TD; + const DataLayout *TD; /// TLI - The target library info if known, otherwise null. const TargetLibraryInfo *TLI; @@ -45,7 +45,7 @@ class PHITransAddr { /// InstInputs - The inputs for our symbolic address. SmallVector<Instruction*, 4> InstInputs; public: - PHITransAddr(Value *addr, const TargetData *td) : Addr(addr), TD(td), TLI(0) { + PHITransAddr(Value *addr, const DataLayout *td) : Addr(addr), TD(td), TLI(0) { // If the address is an instruction, the whole thing is considered an input. if (Instruction *I = dyn_cast<Instruction>(Addr)) InstInputs.push_back(I); diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index c52f846..27726f4 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -180,11 +180,20 @@ namespace llvm { //===--------------------------------------------------------------------===// // - // createLoopDependenceAnalysisPass - This creates an instance of the - // LoopDependenceAnalysis pass. + // createDependenceAnalysisPass - This creates an instance of the + // DependenceAnalysis pass. // - LoopPass *createLoopDependenceAnalysisPass(); + FunctionPass *createDependenceAnalysisPass(); + //===--------------------------------------------------------------------===// + // + // createCostModelAnalysisPass - This creates an instance of the + // CostModelAnalysis pass. + // + FunctionPass *createCostModelAnalysisPass(); + + //===--------------------------------------------------------------------===// + // // 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 index 7025e28..86b1520 100644 --- a/include/llvm/Analysis/PathNumbering.h +++ b/include/llvm/Analysis/PathNumbering.h @@ -26,11 +26,11 @@ #ifndef LLVM_PATH_NUMBERING_H #define LLVM_PATH_NUMBERING_H -#include "llvm/BasicBlock.h" -#include "llvm/Instructions.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 "llvm/Analysis/ProfileInfoTypes.h" #include <map> #include <stack> #include <vector> diff --git a/include/llvm/Analysis/PathProfileInfo.h b/include/llvm/Analysis/PathProfileInfo.h index cef6d2d..8684f41 100644 --- a/include/llvm/Analysis/PathProfileInfo.h +++ b/include/llvm/Analysis/PathProfileInfo.h @@ -14,8 +14,8 @@ #ifndef LLVM_PATHPROFILEINFO_H #define LLVM_PATHPROFILEINFO_H -#include "llvm/BasicBlock.h" #include "llvm/Analysis/PathNumbering.h" +#include "llvm/IR/BasicBlock.h" namespace llvm { diff --git a/include/llvm/Analysis/ProfileDataLoader.h b/include/llvm/Analysis/ProfileDataLoader.h index bec9fac..90097f7 100644 --- a/include/llvm/Analysis/ProfileDataLoader.h +++ b/include/llvm/Analysis/ProfileDataLoader.h @@ -16,6 +16,7 @@ #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" @@ -115,9 +116,6 @@ public: /// been counted yet. static const unsigned Uncounted; - /// The maximum value that can be stored in a profiling counter. - static const unsigned MaxCount; - /// getNumExecutions - Return the number of times the target program was run /// to generate this profiling data. unsigned getNumExecutions() const { return CommandLines.size(); } diff --git a/include/llvm/Analysis/ProfileInfo.h b/include/llvm/Analysis/ProfileInfo.h index 6c2e273..5d17fa1 100644 --- a/include/llvm/Analysis/ProfileInfo.h +++ b/include/llvm/Analysis/ProfileInfo.h @@ -26,9 +26,9 @@ #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <cassert> -#include <string> #include <map> #include <set> +#include <string> namespace llvm { class Pass; diff --git a/include/llvm/Analysis/ProfileInfoLoader.h b/include/llvm/Analysis/ProfileInfoLoader.h index dcf3b38..e0f49f3 100644 --- a/include/llvm/Analysis/ProfileInfoLoader.h +++ b/include/llvm/Analysis/ProfileInfoLoader.h @@ -16,9 +16,9 @@ #ifndef LLVM_ANALYSIS_PROFILEINFOLOADER_H #define LLVM_ANALYSIS_PROFILEINFOLOADER_H -#include <vector> #include <string> #include <utility> +#include <vector> namespace llvm { diff --git a/include/llvm/Analysis/PtrUseVisitor.h b/include/llvm/Analysis/PtrUseVisitor.h new file mode 100644 index 0000000..1802fe8 --- /dev/null +++ b/include/llvm/Analysis/PtrUseVisitor.h @@ -0,0 +1,285 @@ +//===- PtrUseVisitor.h - InstVisitors over a pointers uses ------*- 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 collection of visitors which walk the (instruction) +/// uses of a pointer. These visitors all provide the same essential behavior +/// as an InstVisitor with similar template-based flexibility and +/// implementation strategies. +/// +/// These can be used, for example, to quickly analyze the uses of an alloca, +/// global variable, or function argument. +/// +/// FIXME: Provide a variant which doesn't track offsets and is cheaper. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PTRUSEVISITOR_H +#define LLVM_ANALYSIS_PTRUSEVISITOR_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/InstVisitor.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +namespace detail { +/// \brief Implementation of non-dependent functionality for \c PtrUseVisitor. +/// +/// See \c PtrUseVisitor for the public interface and detailed comments about +/// usage. This class is just a helper base class which is not templated and +/// contains all common code to be shared between different instantiations of +/// PtrUseVisitor. +class PtrUseVisitorBase { +public: + /// \brief This class provides information about the result of a visit. + /// + /// After walking all the users (recursively) of a pointer, the basic + /// infrastructure records some commonly useful information such as escape + /// analysis and whether the visit completed or aborted early. + class PtrInfo { + public: + PtrInfo() : AbortedInfo(0, false), EscapedInfo(0, false) {} + + /// \brief Reset the pointer info, clearing all state. + void reset() { + AbortedInfo.setPointer(0); + AbortedInfo.setInt(false); + EscapedInfo.setPointer(0); + EscapedInfo.setInt(false); + } + + /// \brief Did we abort the visit early? + bool isAborted() const { return AbortedInfo.getInt(); } + + /// \brief Is the pointer escaped at some point? + bool isEscaped() const { return EscapedInfo.getInt(); } + + /// \brief Get the instruction causing the visit to abort. + /// \returns a pointer to the instruction causing the abort if one is + /// available; otherwise returns null. + Instruction *getAbortingInst() const { return AbortedInfo.getPointer(); } + + /// \brief Get the instruction causing the pointer to escape. + /// \returns a pointer to the instruction which escapes the pointer if one + /// is available; otherwise returns null. + Instruction *getEscapingInst() const { return EscapedInfo.getPointer(); } + + /// \brief Mark the visit as aborted. Intended for use in a void return. + /// \param I The instruction which caused the visit to abort, if available. + void setAborted(Instruction *I = 0) { + AbortedInfo.setInt(true); + AbortedInfo.setPointer(I); + } + + /// \brief Mark the pointer as escaped. Intended for use in a void return. + /// \param I The instruction which escapes the pointer, if available. + void setEscaped(Instruction *I = 0) { + EscapedInfo.setInt(true); + EscapedInfo.setPointer(I); + } + + /// \brief Mark the pointer as escaped, and the visit as aborted. Intended + /// for use in a void return. + /// \param I The instruction which both escapes the pointer and aborts the + /// visit, if available. + void setEscapedAndAborted(Instruction *I = 0) { + setEscaped(I); + setAborted(I); + } + + private: + PointerIntPair<Instruction *, 1, bool> AbortedInfo, EscapedInfo; + }; + +protected: + const DataLayout &DL; + + /// \name Visitation infrastructure + /// @{ + + /// \brief The info collected about the pointer being visited thus far. + PtrInfo PI; + + /// \brief A struct of the data needed to visit a particular use. + /// + /// This is used to maintain a worklist fo to-visit uses. This is used to + /// make the visit be iterative rather than recursive. + struct UseToVisit { + typedef PointerIntPair<Use *, 1, bool> UseAndIsOffsetKnownPair; + UseAndIsOffsetKnownPair UseAndIsOffsetKnown; + APInt Offset; + }; + + /// \brief The worklist of to-visit uses. + SmallVector<UseToVisit, 8> Worklist; + + /// \brief A set of visited uses to break cycles in unreachable code. + SmallPtrSet<Use *, 8> VisitedUses; + + /// @} + + + /// \name Per-visit state + /// This state is reset for each instruction visited. + /// @{ + + /// \brief The use currently being visited. + Use *U; + + /// \brief True if we have a known constant offset for the use currently + /// being visited. + bool IsOffsetKnown; + + /// \brief The constant offset of the use if that is known. + APInt Offset; + + /// @} + + + /// Note that the constructor is protected because this class must be a base + /// class, we can't create instances directly of this class. + PtrUseVisitorBase(const DataLayout &DL) : DL(DL) {} + + /// \brief Enqueue the users of this instruction in the visit worklist. + /// + /// This will visit the users with the same offset of the current visit + /// (including an unknown offset if that is the current state). + void enqueueUsers(Instruction &I); + + /// \brief Walk the operands of a GEP and adjust the offset as appropriate. + /// + /// This routine does the heavy lifting of the pointer walk by computing + /// offsets and looking through GEPs. + bool adjustOffsetForGEP(GetElementPtrInst &GEPI); +}; +} // end namespace detail + +/// \brief A base class for visitors over the uses of a pointer value. +/// +/// Once constructed, a user can call \c visit on a pointer value, and this +/// will walk its uses and visit each instruction using an InstVisitor. It also +/// provides visit methods which will recurse through any pointer-to-pointer +/// transformations such as GEPs and bitcasts. +/// +/// During the visit, the current Use* being visited is available to the +/// subclass, as well as the current offset from the original base pointer if +/// known. +/// +/// The recursive visit of uses is accomplished with a worklist, so the only +/// ordering guarantee is that an instruction is visited before any uses of it +/// are visited. Note that this does *not* mean before any of its users are +/// visited! This is because users can be visited multiple times due to +/// multiple, different uses of pointers derived from the same base. +/// +/// A particular Use will only be visited once, but a User may be visited +/// multiple times, once per Use. This visits may notably have different +/// offsets. +/// +/// All visit methods on the underlying InstVisitor return a boolean. This +/// return short-circuits the visit, stopping it immediately. +/// +/// FIXME: Generalize this for all values rather than just instructions. +template <typename DerivedT> +class PtrUseVisitor : protected InstVisitor<DerivedT>, + public detail::PtrUseVisitorBase { + friend class InstVisitor<DerivedT>; + typedef InstVisitor<DerivedT> Base; + +public: + PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) {} + + /// \brief Recursively visit the uses of the given pointer. + /// \returns An info struct about the pointer. See \c PtrInfo for details. + PtrInfo visitPtr(Instruction &I) { + // This must be a pointer type. Get an integer type suitable to hold + // offsets on this pointer. + // FIXME: Support a vector of pointers. + assert(I.getType()->isPointerTy()); + IntegerType *IntPtrTy = cast<IntegerType>(DL.getIntPtrType(I.getType())); + IsOffsetKnown = true; + Offset = APInt(IntPtrTy->getBitWidth(), 0); + PI.reset(); + + // Enqueue the uses of this pointer. + enqueueUsers(I); + + // Visit all the uses off the worklist until it is empty. + while (!Worklist.empty()) { + UseToVisit ToVisit = Worklist.pop_back_val(); + U = ToVisit.UseAndIsOffsetKnown.getPointer(); + IsOffsetKnown = ToVisit.UseAndIsOffsetKnown.getInt(); + if (IsOffsetKnown) + Offset = llvm_move(ToVisit.Offset); + + Instruction *I = cast<Instruction>(U->getUser()); + static_cast<DerivedT*>(this)->visit(I); + if (PI.isAborted()) + break; + } + return PI; + } + +protected: + void visitStoreInst(StoreInst &SI) { + if (SI.getValueOperand() == U->get()) + PI.setEscaped(&SI); + } + + void visitBitCastInst(BitCastInst &BC) { + enqueueUsers(BC); + } + + void visitPtrToIntInst(PtrToIntInst &I) { + PI.setEscaped(&I); + } + + void visitGetElementPtrInst(GetElementPtrInst &GEPI) { + if (GEPI.use_empty()) + return; + + // If we can't walk the GEP, clear the offset. + if (!adjustOffsetForGEP(GEPI)) { + IsOffsetKnown = false; + Offset = APInt(); + } + + // Enqueue the users now that the offset has been adjusted. + enqueueUsers(GEPI); + } + + // No-op intrinsics which we know don't escape the pointer to to logic in + // some other function. + void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) {} + void visitMemIntrinsic(MemIntrinsic &I) {} + void visitIntrinsicInst(IntrinsicInst &II) { + switch (II.getIntrinsicID()) { + default: + return Base::visitIntrinsicInst(II); + + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + return; // No-op intrinsics. + } + } + + // Generically, arguments to calls and invokes escape the pointer to some + // other function. Mark that. + void visitCallSite(CallSite CS) { + PI.setEscaped(CS.getInstruction()); + Base::visitCallSite(CS); + } +}; + +} + +#endif diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index e62040e..48d7ee6 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -54,10 +54,8 @@ class FlatIt {}; /// @brief A RegionNode represents a subregion or a BasicBlock that is part of a /// Region. class RegionNode { - // DO NOT IMPLEMENT - RegionNode(const RegionNode &); - // DO NOT IMPLEMENT - const RegionNode &operator=(const RegionNode &); + RegionNode(const RegionNode &) LLVM_DELETED_FUNCTION; + const RegionNode &operator=(const RegionNode &) LLVM_DELETED_FUNCTION; protected: /// This is the entry basic block that starts this region node. If this is a @@ -203,10 +201,8 @@ inline Region* RegionNode::getNodeAs<Region>() const { /// tree, the second one creates a graphical representation using graphviz. class Region : public RegionNode { friend class RegionInfo; - // DO NOT IMPLEMENT - Region(const Region &); - // DO NOT IMPLEMENT - const Region &operator=(const Region &); + Region(const Region &) LLVM_DELETED_FUNCTION; + const Region &operator=(const Region &) LLVM_DELETED_FUNCTION; // Information necessary to manage this Region. RegionInfo* RI; @@ -565,10 +561,8 @@ class RegionInfo : public FunctionPass { typedef DenseMap<BasicBlock*, Region*> BBtoRegionMap; typedef SmallPtrSet<Region*, 4> RegionSet; - // DO NOT IMPLEMENT - RegionInfo(const RegionInfo &); - // DO NOT IMPLEMENT - const RegionInfo &operator=(const RegionInfo &); + RegionInfo(const RegionInfo &) LLVM_DELETED_FUNCTION; + const RegionInfo &operator=(const RegionInfo &) LLVM_DELETED_FUNCTION; DominatorTree *DT; PostDominatorTree *PDT; diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h index 7adc71c..bcff227 100644 --- a/include/llvm/Analysis/RegionIterator.h +++ b/include/llvm/Analysis/RegionIterator.h @@ -12,8 +12,8 @@ #define LLVM_ANALYSIS_REGION_ITERATOR_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/Support/CFG.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h index 68f1201..54f96d6 100644 --- a/include/llvm/Analysis/RegionPass.h +++ b/include/llvm/Analysis/RegionPass.h @@ -17,11 +17,9 @@ #define LLVM_REGION_PASS_H #include "llvm/Analysis/RegionInfo.h" - +#include "llvm/IR/Function.h" #include "llvm/Pass.h" #include "llvm/PassManagers.h" -#include "llvm/Function.h" - #include <deque> namespace llvm { @@ -59,6 +57,9 @@ public: /// @return The pass to print the LLVM IR in the region. Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + using llvm::Pass::doInitialization; + using llvm::Pass::doFinalization; + virtual bool doInitialization(Region *R, RGPassManager &RGM) { return false; } virtual bool doFinalization() { return false; } //@} diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index c213ade..f8f261f 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -21,16 +21,16 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTION_H #define LLVM_ANALYSIS_SCALAREVOLUTION_H +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Operator.h" #include "llvm/Pass.h" -#include "llvm/Instructions.h" -#include "llvm/Function.h" -#include "llvm/Operator.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ConstantRange.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ValueHandle.h" #include <map> namespace llvm { @@ -40,7 +40,7 @@ namespace llvm { class DominatorTree; class Type; class ScalarEvolution; - class TargetData; + class DataLayout; class TargetLibraryInfo; class LLVMContext; class Loop; @@ -70,8 +70,8 @@ namespace llvm { unsigned short SubclassData; private: - SCEV(const SCEV &); // DO NOT IMPLEMENT - void operator=(const SCEV &); // DO NOT IMPLEMENT + SCEV(const SCEV &) LLVM_DELETED_FUNCTION; + void operator=(const SCEV &) LLVM_DELETED_FUNCTION; public: /// NoWrapFlags are bitfield indices into SubclassData. @@ -162,7 +162,6 @@ namespace llvm { SCEVCouldNotCompute(); /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVCouldNotCompute *S) { return true; } static bool classof(const SCEV *S); }; @@ -227,7 +226,7 @@ namespace llvm { /// TD - The target data information for the target we are targeting. /// - TargetData *TD; + DataLayout *TD; /// TLI - The target library information for the target we are targeting. /// @@ -874,6 +873,7 @@ namespace llvm { virtual void releaseMemory(); virtual void getAnalysisUsage(AnalysisUsage &AU) const; virtual void print(raw_ostream &OS, const Module* = 0) const; + virtual void verifyAnalysis() const; private: FoldingSet<SCEV> UniqueSCEVs; diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 3f8f149..ea45aff 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -14,15 +14,15 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H #define LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H -#include "llvm/IRBuilder.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/Support/TargetFolder.h" #include "llvm/Support/ValueHandle.h" #include <set> namespace llvm { - class TargetLowering; + class TargetTransformInfo; /// Return true if the given expression is safe to expand in the sense that /// all materialized values are safe to speculate. @@ -129,7 +129,7 @@ namespace llvm { /// representative. Return the number of phis eliminated. unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT, SmallVectorImpl<WeakVH> &DeadInsts, - const TargetLowering *TLI = NULL); + const TargetTransformInfo *TTI = NULL); /// expandCodeFor - Insert code to directly compute the specified SCEV /// expression into the program. The inserted code is inserted into the diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index ded1297..b74cb33 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -14,8 +14,8 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H #define LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H -#include "llvm/Analysis/ScalarEvolution.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -46,7 +46,6 @@ namespace llvm { Type *getType() const { return V->getType(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVConstant *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scConstant; } @@ -68,7 +67,6 @@ namespace llvm { Type *getType() const { return Ty; } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVCastExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scTruncate || S->getSCEVType() == scZeroExtend || @@ -88,7 +86,6 @@ namespace llvm { public: /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVTruncateExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scTruncate; } @@ -106,7 +103,6 @@ namespace llvm { public: /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVZeroExtendExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scZeroExtend; } @@ -124,7 +120,6 @@ namespace llvm { public: /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVSignExtendExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scSignExtend; } @@ -166,7 +161,6 @@ namespace llvm { } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVNAryExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || @@ -188,7 +182,6 @@ namespace llvm { public: /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVCommutativeExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || @@ -223,7 +216,6 @@ namespace llvm { } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVAddExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scAddExpr; } @@ -242,7 +234,6 @@ namespace llvm { public: /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVMulExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scMulExpr; } @@ -274,7 +265,6 @@ namespace llvm { } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVUDivExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scUDivExpr; } @@ -358,7 +348,6 @@ namespace llvm { } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVAddRecExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scAddRecExpr; } @@ -380,7 +369,6 @@ namespace llvm { public: /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVSMaxExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scSMaxExpr; } @@ -402,7 +390,6 @@ namespace llvm { public: /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVUMaxExpr *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scUMaxExpr; } @@ -449,7 +436,6 @@ namespace llvm { Type *getType() const { return getValPtr()->getType(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVUnknown *S) { return true; } static inline bool classof(const SCEV *S) { return S->getSCEVType() == scUnknown; } diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h index c3c2f4b..604e306 100644 --- a/include/llvm/Analysis/SparsePropagation.h +++ b/include/llvm/Analysis/SparsePropagation.h @@ -17,8 +17,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" -#include <vector> #include <set> +#include <vector> namespace llvm { class Value; @@ -130,9 +130,9 @@ class SparseSolver { /// PHI nodes retriggered. typedef std::pair<BasicBlock*,BasicBlock*> Edge; std::set<Edge> KnownFeasibleEdges; - - SparseSolver(const SparseSolver&); // DO NOT IMPLEMENT - void operator=(const SparseSolver&); // DO NOT IMPLEMENT + + SparseSolver(const SparseSolver&) LLVM_DELETED_FUNCTION; + void operator=(const SparseSolver&) LLVM_DELETED_FUNCTION; public: explicit SparseSolver(AbstractLatticeFunction *Lattice) : LatticeFunc(Lattice) {} diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h new file mode 100644 index 0000000..ddf615f --- /dev/null +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -0,0 +1,206 @@ +//===- llvm/Analysis/TargetTransformInfo.h ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass exposes codegen information to IR-level passes. Every +// transformation that uses codegen information is broken into three parts: +// 1. The IR-level analysis pass. +// 2. The IR-level transformation interface which provides the needed +// information. +// 3. Codegen-level implementation which uses target-specific hooks. +// +// This file defines #2, which is the interface that IR-level transformations +// use for querying the codegen. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGET_TRANSFORM_INTERFACE +#define LLVM_ANALYSIS_TARGET_TRANSFORM_INTERFACE + +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Type.h" +#include "llvm/Pass.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +/// TargetTransformInfo - This pass provides access to the codegen +/// interfaces that are needed for IR-level transformations. +class TargetTransformInfo { +protected: + /// \brief The TTI instance one level down the stack. + /// + /// This is used to implement the default behavior all of the methods which + /// is to delegate up through the stack of TTIs until one can answer the + /// query. + TargetTransformInfo *PrevTTI; + + /// \brief The top of the stack of TTI analyses available. + /// + /// This is a convenience routine maintained as TTI analyses become available + /// that complements the PrevTTI delegation chain. When one part of an + /// analysis pass wants to query another part of the analysis pass it can use + /// this to start back at the top of the stack. + TargetTransformInfo *TopTTI; + + /// All pass subclasses must in their initializePass routine call + /// pushTTIStack with themselves to update the pointers tracking the previous + /// TTI instance in the analysis group's stack, and the top of the analysis + /// group's stack. + void pushTTIStack(Pass *P); + + /// All pass subclasses must in their finalizePass routine call popTTIStack + /// to update the pointers tracking the previous TTI instance in the analysis + /// group's stack, and the top of the analysis group's stack. + void popTTIStack(); + + /// All pass subclasses must call TargetTransformInfo::getAnalysisUsage. + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + +public: + /// This class is intended to be subclassed by real implementations. + virtual ~TargetTransformInfo() = 0; + + /// \name Scalar Target Information + /// @{ + + /// \brief Flags indicating the kind of support for population count. + /// + /// Compared to the SW implementation, HW support is supposed to + /// significantly boost the performance when the population is dense, and it + /// may or may not degrade performance if the population is sparse. A HW + /// support is considered as "Fast" if it can outperform, or is on a par + /// with, SW implementaion when the population is sparse; otherwise, it is + /// considered as "Slow". + enum PopcntSupportKind { + PSK_Software, + PSK_SlowHardware, + PSK_FastHardware + }; + + /// isLegalAddImmediate - Return true if the specified immediate is legal + /// add immediate, that is the target has add instructions which can add + /// a register with the immediate without having to materialize the + /// immediate into a register. + virtual bool isLegalAddImmediate(int64_t Imm) const; + + /// isLegalICmpImmediate - Return true if the specified immediate is legal + /// icmp immediate, that is the target has icmp instructions which can compare + /// a register against the immediate without having to materialize the + /// immediate into a register. + virtual bool isLegalICmpImmediate(int64_t Imm) const; + + /// isLegalAddressingMode - Return true if the addressing mode represented by + /// AM is legal for this target, for a load/store of the specified type. + /// The type may be VoidTy, in which case only return true if the addressing + /// mode is legal for a load/store of any legal type. + /// TODO: Handle pre/postinc as well. + virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) const; + + /// isTruncateFree - Return true if it's free to truncate a value of + /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in + /// register EAX to i16 by referencing its sub-register AX. + virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const; + + /// Is this type legal. + virtual bool isTypeLegal(Type *Ty) const; + + /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes + virtual unsigned getJumpBufAlignment() const; + + /// getJumpBufSize - returns the target's jmp_buf size in bytes. + virtual unsigned getJumpBufSize() const; + + /// shouldBuildLookupTables - Return true if switches should be turned into + /// lookup tables for the target. + virtual bool shouldBuildLookupTables() const; + + /// getPopcntSupport - Return hardware support for population count. + virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) 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; + + /// @} + + /// \name Vector Target Information + /// @{ + + /// \brief The various kinds of shuffle patterns for vector queries. + enum ShuffleKind { + SK_Broadcast, ///< Broadcast element 0 to all other elements. + SK_Reverse, ///< Reverse the order of the vector. + SK_InsertSubvector, ///< InsertSubvector. Index indicates start offset. + SK_ExtractSubvector ///< ExtractSubvector Index indicates start offset. + }; + + /// \return The number of scalar or vector registers that the target has. + /// If 'Vectors' is true, it returns the number of vector registers. If it is + /// set to false, it returns the number of scalar registers. + virtual unsigned getNumberOfRegisters(bool Vector) const; + + /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. + virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty) const; + + /// \return The cost of a shuffle instruction of kind Kind and of type Tp. + /// The index and subtype parameters are used by the subvector insertion and + /// extraction shuffle kinds. + virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, + Type *SubTp = 0) const; + + /// \return The expected cost of cast instructions, such as bitcast, trunc, + /// zext, etc. + virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, + Type *Src) const; + + /// \return The expected cost of control-flow related instrutctions such as + /// Phi, Ret, Br. + virtual unsigned getCFInstrCost(unsigned Opcode) const; + + /// \returns The expected cost of compare and select instructions. + virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy = 0) const; + + /// \return The expected cost of vector Insert and Extract. + /// Use -1 to indicate that there is no information on the index value. + virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index = -1) const; + + /// \return The cost of Load and Store instructions. + virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) const; + + /// \returns The cost of Intrinsic instructions. + virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) const; + + /// \returns The number of pieces into which the provided type must be + /// split during legalization. Zero is returned when the answer is unknown. + virtual unsigned getNumberOfParts(Type *Tp) const; + + /// @} + + /// Analysis group identification. + static char ID; +}; + +/// \brief Create the base case instance of a pass in the TTI analysis group. +/// +/// This class provides the base case for the stack of TTI analyses. It doesn't +/// delegate to anything and uses the STTI and VTTI objects passed in to +/// satisfy the queries. +ImmutablePass *createNoTargetTransformInfoPass(); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/Trace.h b/include/llvm/Analysis/Trace.h index 99651e1..26947fe 100644 --- a/include/llvm/Analysis/Trace.h +++ b/include/llvm/Analysis/Trace.h @@ -18,8 +18,8 @@ #ifndef LLVM_ANALYSIS_TRACE_H #define LLVM_ANALYSIS_TRACE_H -#include <vector> #include <cassert> +#include <vector> namespace llvm { class BasicBlock; diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index e8d45f6..875c47d 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -22,7 +22,7 @@ namespace llvm { class Value; class Instruction; class APInt; - class TargetData; + class DataLayout; class StringRef; class MDNode; @@ -37,27 +37,26 @@ namespace llvm { /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. void ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne, - const TargetData *TD = 0, unsigned Depth = 0); + const DataLayout *TD = 0, unsigned Depth = 0); void computeMaskedBitsLoad(const MDNode &Ranges, APInt &KnownZero); /// ComputeSignBit - Determine whether the sign bit is known to be zero or /// one. Convenience wrapper around ComputeMaskedBits. void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, - const TargetData *TD = 0, unsigned Depth = 0); + const DataLayout *TD = 0, unsigned Depth = 0); - /// isPowerOfTwo - Return true if the given value is known to have exactly one - /// bit set when defined. For vectors return true if every element is known to - /// be a power of two when defined. Supports values with integer or pointer - /// type and vectors of integers. If 'OrZero' is set then returns true if the - /// given value is either a power of two or zero. - bool isPowerOfTwo(Value *V, const TargetData *TD = 0, bool OrZero = false, - unsigned Depth = 0); + /// isKnownToBeAPowerOfTwo - Return true if the given value is known to have + /// exactly one bit set when defined. For vectors return true if every + /// element is known to be a power of two when defined. Supports values with + /// integer or pointer type and vectors of integers. If 'OrZero' is set then + /// returns true if the given value is either a power of two or zero. + bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0); /// isKnownNonZero - Return true if the given value is known to be non-zero /// when defined. For vectors return true if every element is known to be /// non-zero when defined. Supports values with integer or pointer type and /// vectors of integers. - bool isKnownNonZero(Value *V, const TargetData *TD = 0, unsigned Depth = 0); + bool isKnownNonZero(Value *V, const DataLayout *TD = 0, unsigned Depth = 0); /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use /// this predicate to simplify operations downstream. Mask is known to be @@ -69,7 +68,7 @@ namespace llvm { /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. bool MaskedValueIsZero(Value *V, const APInt &Mask, - const TargetData *TD = 0, unsigned Depth = 0); + const DataLayout *TD = 0, unsigned Depth = 0); /// ComputeNumSignBits - Return the number of times the sign bit of the @@ -80,7 +79,7 @@ namespace llvm { /// /// 'Op' must have a scalar integer type. /// - unsigned ComputeNumSignBits(Value *Op, const TargetData *TD = 0, + unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = 0, unsigned Depth = 0); /// ComputeMultiple - This function computes the integer multiple of Base that @@ -118,10 +117,10 @@ namespace llvm { /// it can be expressed as a base pointer plus a constant offset. Return the /// base and offset to the caller. Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, - const TargetData &TD); + const DataLayout &TD); static inline const Value * GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset, - const TargetData &TD) { + const DataLayout &TD) { return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD); } @@ -143,10 +142,10 @@ namespace llvm { /// being addressed. Note that the returned value has pointer type if the /// specified value does. If the MaxLookup value is non-zero, it limits the /// number of instructions to be stripped off. - Value *GetUnderlyingObject(Value *V, const TargetData *TD = 0, + Value *GetUnderlyingObject(Value *V, const DataLayout *TD = 0, unsigned MaxLookup = 6); static inline const Value * - GetUnderlyingObject(const Value *V, const TargetData *TD = 0, + GetUnderlyingObject(const Value *V, const DataLayout *TD = 0, unsigned MaxLookup = 6) { return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup); } @@ -156,7 +155,7 @@ namespace llvm { /// multiple objects. void GetUnderlyingObjects(Value *V, SmallVectorImpl<Value *> &Objects, - const TargetData *TD = 0, + const DataLayout *TD = 0, unsigned MaxLookup = 6); /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer @@ -182,7 +181,7 @@ namespace llvm { /// However, this method can return true for instructions that read memory; /// for such instructions, moving them may change the resulting value. bool isSafeToSpeculativelyExecute(const Value *V, - const TargetData *TD = 0); + const DataLayout *TD = 0); } // end namespace llvm diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h deleted file mode 100644 index 0228d86..0000000 --- a/include/llvm/Attributes.h +++ /dev/null @@ -1,410 +0,0 @@ -//===-- llvm/Attributes.h - Container for Attributes ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the simple types necessary to represent the -// attributes associated with functions and their calls. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ATTRIBUTES_H -#define LLVM_ATTRIBUTES_H - -#include "llvm/Support/MathExtras.h" -#include "llvm/ADT/ArrayRef.h" -#include <cassert> -#include <string> - -namespace llvm { -class Type; - -namespace Attribute { -/// We use this proxy POD type to allow constructing Attributes constants -/// using initializer lists. Do not use this class directly. -struct AttrConst { - uint64_t v; - AttrConst operator | (const AttrConst Attrs) const { - AttrConst Res = {v | Attrs.v}; - return Res; - } - AttrConst operator ~ () const { - AttrConst Res = {~v}; - return Res; - } -}; -} // namespace Attribute - - -/// Attributes - A bitset of attributes. -class Attributes { - public: - Attributes() : Bits(0) { } - explicit Attributes(uint64_t Val) : Bits(Val) { } - /*implicit*/ Attributes(Attribute::AttrConst Val) : Bits(Val.v) { } - // This is a "safe bool() operator". - operator const void *() const { return Bits ? this : 0; } - bool isEmptyOrSingleton() const { return (Bits & (Bits - 1)) == 0; } - bool operator == (const Attributes &Attrs) const { - return Bits == Attrs.Bits; - } - bool operator != (const Attributes &Attrs) const { - return Bits != Attrs.Bits; - } - Attributes operator | (const Attributes &Attrs) const { - return Attributes(Bits | Attrs.Bits); - } - Attributes operator & (const Attributes &Attrs) const { - return Attributes(Bits & Attrs.Bits); - } - Attributes operator ^ (const Attributes &Attrs) const { - return Attributes(Bits ^ Attrs.Bits); - } - Attributes &operator |= (const Attributes &Attrs) { - Bits |= Attrs.Bits; - return *this; - } - Attributes &operator &= (const Attributes &Attrs) { - Bits &= Attrs.Bits; - return *this; - } - Attributes operator ~ () const { return Attributes(~Bits); } - uint64_t Raw() const { return Bits; } - private: - // Currently, we need less than 64 bits. - uint64_t Bits; -}; - -namespace Attribute { - -/// Function parameters and results can have attributes to indicate how they -/// should be treated by optimizations and code generation. This enumeration -/// lists the attributes that can be associated with parameters, function -/// results or the function itself. -/// @brief Function attributes. - -// We declare AttrConst objects that will be used throughout the code -// and also raw uint64_t objects with _i suffix to be used below for other -// constant declarations. This is done to avoid static CTORs and at the same -// time to keep type-safety of Attributes. -#define DECLARE_LLVM_ATTRIBUTE(name, value) \ - const uint64_t name##_i = value; \ - const AttrConst name = {value}; - -DECLARE_LLVM_ATTRIBUTE(None,0) ///< No attributes have been set -DECLARE_LLVM_ATTRIBUTE(ZExt,1<<0) ///< Zero extended before/after call -DECLARE_LLVM_ATTRIBUTE(SExt,1<<1) ///< Sign extended before/after call -DECLARE_LLVM_ATTRIBUTE(NoReturn,1<<2) ///< Mark the function as not returning -DECLARE_LLVM_ATTRIBUTE(InReg,1<<3) ///< Force argument to be passed in register -DECLARE_LLVM_ATTRIBUTE(StructRet,1<<4) ///< Hidden pointer to structure to return -DECLARE_LLVM_ATTRIBUTE(NoUnwind,1<<5) ///< Function doesn't unwind stack -DECLARE_LLVM_ATTRIBUTE(NoAlias,1<<6) ///< Considered to not alias after call -DECLARE_LLVM_ATTRIBUTE(ByVal,1<<7) ///< Pass structure by value -DECLARE_LLVM_ATTRIBUTE(Nest,1<<8) ///< Nested function static chain -DECLARE_LLVM_ATTRIBUTE(ReadNone,1<<9) ///< Function does not access memory -DECLARE_LLVM_ATTRIBUTE(ReadOnly,1<<10) ///< Function only reads from memory -DECLARE_LLVM_ATTRIBUTE(NoInline,1<<11) ///< inline=never -DECLARE_LLVM_ATTRIBUTE(AlwaysInline,1<<12) ///< inline=always -DECLARE_LLVM_ATTRIBUTE(OptimizeForSize,1<<13) ///< opt_size -DECLARE_LLVM_ATTRIBUTE(StackProtect,1<<14) ///< Stack protection. -DECLARE_LLVM_ATTRIBUTE(StackProtectReq,1<<15) ///< Stack protection required. -DECLARE_LLVM_ATTRIBUTE(Alignment,31<<16) ///< Alignment of parameter (5 bits) - // stored as log2 of alignment with +1 bias - // 0 means unaligned different from align 1 -DECLARE_LLVM_ATTRIBUTE(NoCapture,1<<21) ///< Function creates no aliases of pointer -DECLARE_LLVM_ATTRIBUTE(NoRedZone,1<<22) /// disable redzone -DECLARE_LLVM_ATTRIBUTE(NoImplicitFloat,1<<23) /// disable implicit floating point - /// instructions. -DECLARE_LLVM_ATTRIBUTE(Naked,1<<24) ///< Naked function -DECLARE_LLVM_ATTRIBUTE(InlineHint,1<<25) ///< source said inlining was - ///desirable -DECLARE_LLVM_ATTRIBUTE(StackAlignment,7<<26) ///< Alignment of stack for - ///function (3 bits) stored as log2 - ///of alignment with +1 bias - ///0 means unaligned (different from - ///alignstack= {1)) -DECLARE_LLVM_ATTRIBUTE(ReturnsTwice,1<<29) ///< Function can return twice -DECLARE_LLVM_ATTRIBUTE(UWTable,1<<30) ///< Function must be in a unwind - ///table -DECLARE_LLVM_ATTRIBUTE(NonLazyBind,1U<<31) ///< Function is called early and/or - /// often, so lazy binding isn't - /// worthwhile. -DECLARE_LLVM_ATTRIBUTE(AddressSafety,1ULL<<32) ///< Address safety checking is on. - -#undef DECLARE_LLVM_ATTRIBUTE - -/// Note that uwtable is about the ABI or the user mandating an entry in the -/// unwind table. The nounwind attribute is about an exception passing by the -/// function. -/// In a theoretical system that uses tables for profiling and sjlj for -/// exceptions, they would be fully independent. In a normal system that -/// uses tables for both, the semantics are: -/// nil = Needs an entry because an exception might pass by. -/// nounwind = No need for an entry -/// uwtable = Needs an entry because the ABI says so and because -/// an exception might pass by. -/// uwtable + nounwind = Needs an entry because the ABI says so. - -/// @brief Attributes that only apply to function parameters. -const AttrConst ParameterOnly = {ByVal_i | Nest_i | - StructRet_i | NoCapture_i}; - -/// @brief Attributes that may be applied to the function itself. These cannot -/// be used on return values or function parameters. -const AttrConst FunctionOnly = {NoReturn_i | NoUnwind_i | ReadNone_i | - ReadOnly_i | NoInline_i | AlwaysInline_i | OptimizeForSize_i | - StackProtect_i | StackProtectReq_i | NoRedZone_i | NoImplicitFloat_i | - Naked_i | InlineHint_i | StackAlignment_i | - UWTable_i | NonLazyBind_i | ReturnsTwice_i | AddressSafety_i}; - -/// @brief Parameter attributes that do not apply to vararg call arguments. -const AttrConst VarArgsIncompatible = {StructRet_i}; - -/// @brief Attributes that are mutually incompatible. -const AttrConst MutuallyIncompatible[5] = { - {ByVal_i | Nest_i | StructRet_i}, - {ByVal_i | Nest_i | InReg_i }, - {ZExt_i | SExt_i}, - {ReadNone_i | ReadOnly_i}, - {NoInline_i | AlwaysInline_i} -}; - -/// @brief Which attributes cannot be applied to a type. -Attributes typeIncompatible(Type *Ty); - -/// This turns an int alignment (a power of 2, normally) into the -/// form used internally in Attributes. -inline Attributes constructAlignmentFromInt(unsigned i) { - // Default alignment, allow the target to define how to align it. - if (i == 0) - return None; - - assert(isPowerOf2_32(i) && "Alignment must be a power of two."); - assert(i <= 0x40000000 && "Alignment too large."); - return Attributes((Log2_32(i)+1) << 16); -} - -/// This returns the alignment field of an attribute as a byte alignment value. -inline unsigned getAlignmentFromAttrs(Attributes A) { - Attributes Align = A & Attribute::Alignment; - if (!Align) - return 0; - - return 1U << ((Align.Raw() >> 16) - 1); -} - -/// This turns an int stack alignment (which must be a power of 2) into -/// the form used internally in Attributes. -inline Attributes constructStackAlignmentFromInt(unsigned i) { - // Default alignment, allow the target to define how to align it. - if (i == 0) - return None; - - assert(isPowerOf2_32(i) && "Alignment must be a power of two."); - assert(i <= 0x100 && "Alignment too large."); - return Attributes((Log2_32(i)+1) << 26); -} - -/// This returns the stack alignment field of an attribute as a byte alignment -/// value. -inline unsigned getStackAlignmentFromAttrs(Attributes A) { - Attributes StackAlign = A & Attribute::StackAlignment; - if (!StackAlign) - return 0; - - return 1U << ((StackAlign.Raw() >> 26) - 1); -} - -/// This returns an integer containing an encoding of all the -/// LLVM attributes found in the given attribute bitset. Any -/// change to this encoding is a breaking change to bitcode -/// compatibility. -inline uint64_t encodeLLVMAttributesForBitcode(Attributes Attrs) { - // FIXME: It doesn't make sense to store the alignment information as an - // expanded out value, we should store it as a log2 value. However, we can't - // just change that here without breaking bitcode compatibility. If this ever - // becomes a problem in practice, we should introduce new tag numbers in the - // bitcode file and have those tags use a more efficiently encoded alignment - // field. - - // Store the alignment in the bitcode as a 16-bit raw value instead of a - // 5-bit log2 encoded value. Shift the bits above the alignment up by - // 11 bits. - - uint64_t EncodedAttrs = Attrs.Raw() & 0xffff; - if (Attrs & Attribute::Alignment) - EncodedAttrs |= (1ull << 16) << - (((Attrs & Attribute::Alignment).Raw()-1) >> 16); - EncodedAttrs |= (Attrs.Raw() & (0xfffull << 21)) << 11; - - return EncodedAttrs; -} - -/// This returns an attribute bitset containing the LLVM attributes -/// that have been decoded from the given integer. This function -/// must stay in sync with 'encodeLLVMAttributesForBitcode'. -inline Attributes decodeLLVMAttributesForBitcode(uint64_t EncodedAttrs) { - // The alignment is stored as a 16-bit raw value from bits 31--16. - // We shift the bits above 31 down by 11 bits. - - unsigned Alignment = (EncodedAttrs & (0xffffull << 16)) >> 16; - assert((!Alignment || isPowerOf2_32(Alignment)) && - "Alignment must be a power of two."); - - Attributes Attrs(EncodedAttrs & 0xffff); - if (Alignment) - Attrs |= Attribute::constructAlignmentFromInt(Alignment); - Attrs |= Attributes((EncodedAttrs & (0xfffull << 32)) >> 11); - - return Attrs; -} - - -/// The set of Attributes set in Attributes is converted to a -/// string of equivalent mnemonics. This is, presumably, for writing out -/// the mnemonics for the assembly writer. -/// @brief Convert attribute bits to text -std::string getAsString(Attributes Attrs); -} // end namespace Attribute - -/// This is just a pair of values to associate a set of attributes -/// with an index. -struct AttributeWithIndex { - Attributes Attrs; ///< The attributes that are set, or'd together. - unsigned Index; ///< Index of the parameter for which the attributes apply. - ///< Index 0 is used for return value attributes. - ///< Index ~0U is used for function attributes. - - static AttributeWithIndex get(unsigned Idx, Attributes Attrs) { - AttributeWithIndex P; - P.Index = Idx; - P.Attrs = Attrs; - return P; - } -}; - -//===----------------------------------------------------------------------===// -// AttrListPtr Smart Pointer -//===----------------------------------------------------------------------===// - -class AttributeListImpl; - -/// AttrListPtr - This class manages the ref count for the opaque -/// AttributeListImpl object and provides accessors for it. -class AttrListPtr { - /// AttrList - The attributes that we are managing. This can be null - /// to represent the empty attributes list. - AttributeListImpl *AttrList; -public: - AttrListPtr() : AttrList(0) {} - AttrListPtr(const AttrListPtr &P); - const AttrListPtr &operator=(const AttrListPtr &RHS); - ~AttrListPtr(); - - //===--------------------------------------------------------------------===// - // Attribute List Construction and Mutation - //===--------------------------------------------------------------------===// - - /// get - Return a Attributes list with the specified parameters in it. - static AttrListPtr get(ArrayRef<AttributeWithIndex> Attrs); - - /// addAttr - Add the specified attribute at the specified index to this - /// attribute list. Since attribute lists are immutable, this - /// returns the new list. - AttrListPtr addAttr(unsigned Idx, Attributes Attrs) const; - - /// removeAttr - Remove the specified attribute at the specified index from - /// this attribute list. Since attribute lists are immutable, this - /// returns the new list. - AttrListPtr removeAttr(unsigned Idx, Attributes Attrs) const; - - //===--------------------------------------------------------------------===// - // Attribute List Accessors - //===--------------------------------------------------------------------===// - /// getParamAttributes - The attributes for the specified index are - /// returned. - Attributes getParamAttributes(unsigned Idx) const { - assert (Idx && Idx != ~0U && "Invalid parameter index!"); - return getAttributes(Idx); - } - - /// getRetAttributes - The attributes for the ret value are - /// returned. - Attributes getRetAttributes() const { - return getAttributes(0); - } - - /// getFnAttributes - The function attributes are returned. - Attributes getFnAttributes() const { - return getAttributes(~0U); - } - - /// paramHasAttr - Return true if the specified parameter index has the - /// specified attribute set. - bool paramHasAttr(unsigned Idx, Attributes Attr) const { - return getAttributes(Idx) & Attr; - } - - /// getParamAlignment - Return the alignment for the specified function - /// parameter. - unsigned getParamAlignment(unsigned Idx) const { - return Attribute::getAlignmentFromAttrs(getAttributes(Idx)); - } - - /// hasAttrSomewhere - Return true if the specified attribute is set for at - /// least one parameter or for the return value. - bool hasAttrSomewhere(Attributes Attr) const; - - /// operator==/!= - Provide equality predicates. - bool operator==(const AttrListPtr &RHS) const - { return AttrList == RHS.AttrList; } - bool operator!=(const AttrListPtr &RHS) const - { return AttrList != RHS.AttrList; } - - void dump() const; - - //===--------------------------------------------------------------------===// - // Attribute List Introspection - //===--------------------------------------------------------------------===// - - /// getRawPointer - Return a raw pointer that uniquely identifies this - /// attribute list. - void *getRawPointer() const { - return AttrList; - } - - // Attributes are stored as a dense set of slots, where there is one - // slot for each argument that has an attribute. This allows walking over the - // dense set instead of walking the sparse list of attributes. - - /// isEmpty - Return true if there are no attributes. - /// - bool isEmpty() const { - return AttrList == 0; - } - - /// getNumSlots - Return the number of slots used in this attribute list. - /// This is the number of arguments that have an attribute set on them - /// (including the function itself). - unsigned getNumSlots() const; - - /// getSlot - Return the AttributeWithIndex at the specified slot. This - /// holds a index number plus a set of attributes. - const AttributeWithIndex &getSlot(unsigned Slot) const; - -private: - explicit AttrListPtr(AttributeListImpl *L); - - /// getAttributes - The attributes for the specified index are - /// returned. Attributes for the result are denoted with Idx = 0. - Attributes getAttributes(unsigned Idx) const; - -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Bitcode/Archive.h b/include/llvm/Bitcode/Archive.h index c1c3ec0..7b30c7e 100644 --- a/include/llvm/Bitcode/Archive.h +++ b/include/llvm/Bitcode/Archive.h @@ -50,10 +50,10 @@ class ArchiveMember : public ilist_node<ArchiveMember> { SVR4SymbolTableFlag = 1, ///< Member is a SVR4 symbol table BSD4SymbolTableFlag = 2, ///< Member is a BSD4 symbol table LLVMSymbolTableFlag = 4, ///< Member is an LLVM symbol table - BitcodeFlag = 8, ///< Member is bitcode - HasPathFlag = 16, ///< Member has a full or partial path + BitcodeFlag = 8, ///< Member is bitcode + HasPathFlag = 16, ///< Member has a full or partial path HasLongFilenameFlag = 32, ///< Member uses the long filename syntax - StringTableFlag = 64 ///< Member is an ar(1) format string table + StringTableFlag = 64 ///< Member is an ar(1) format string table }; /// @} @@ -527,9 +527,9 @@ class Archive { /// @name Hidden /// @{ private: - Archive(); ///< Do not implement - Archive(const Archive&); ///< Do not implement - Archive& operator=(const Archive&); ///< Do not implement + Archive() LLVM_DELETED_FUNCTION; + Archive(const Archive&) LLVM_DELETED_FUNCTION; + Archive& operator=(const Archive&) LLVM_DELETED_FUNCTION; /// @} }; diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index 28e1ab1..b510daf 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -26,8 +26,8 @@ namespace llvm { namespace bitc { enum StandardWidths { - BlockIDWidth = 8, // We use VBR-8 for block IDs. - CodeLenWidth = 4, // Codelen are VBR-4. + BlockIDWidth = 8, // We use VBR-8 for block IDs. + CodeLenWidth = 4, // Codelen are VBR-4. BlockSizeWidth = 32 // BlockSize up to 2^32 32-bit words = 16GB per block. }; @@ -69,10 +69,11 @@ namespace bitc { enum BlockInfoCodes { // DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd // block, instead of the BlockInfo block. - - BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#] - BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name] - BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME: [id, name] + + BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#] + BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name] + BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME: + // [id, name] }; } // End bitc namespace @@ -99,7 +100,7 @@ public: explicit BitCodeAbbrevOp(Encoding E, uint64_t Data = 0) : Val(Data), IsLiteral(false), Enc(E) {} - bool isLiteral() const { return IsLiteral; } + bool isLiteral() const { return IsLiteral; } bool isEncoding() const { return !IsLiteral; } // Accessors for literals. @@ -138,18 +139,18 @@ public: if (C >= 'a' && C <= 'z') return C-'a'; if (C >= 'A' && C <= 'Z') return C-'A'+26; if (C >= '0' && C <= '9') return C-'0'+26+26; - if (C == '.') return 62; - if (C == '_') return 63; + if (C == '.') return 62; + if (C == '_') return 63; llvm_unreachable("Not a value Char6 character!"); } static char DecodeChar6(unsigned V) { assert((V & ~63) == 0 && "Not a Char6 encoded character!"); - if (V < 26) return V+'a'; - if (V < 26+26) return V-26+'A'; + if (V < 26) return V+'a'; + if (V < 26+26) return V-26+'A'; if (V < 26+26+10) return V-26-26+'0'; - if (V == 62) return '.'; - if (V == 63) return '_'; + if (V == 62) return '.'; + if (V == 63) return '_'; llvm_unreachable("Not a value Char6 character!"); } diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 6586829..5b60f72 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -35,21 +35,21 @@ public: unsigned BlockID; std::vector<BitCodeAbbrev*> Abbrevs; std::string Name; - + std::vector<std::pair<unsigned, std::string> > RecordNames; }; private: OwningPtr<StreamableMemoryObject> BitcodeBytes; - + std::vector<BlockInfo> BlockInfoRecords; /// IgnoreBlockInfoNames - This is set to true if we don't care about the /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer /// uses this. bool IgnoreBlockInfoNames; - - BitstreamReader(const BitstreamReader&); // DO NOT IMPLEMENT - void operator=(const BitstreamReader&); // DO NOT IMPLEMENT + + BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION; + void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION; public: BitstreamReader() : IgnoreBlockInfoNames(true) { } @@ -86,7 +86,7 @@ public: /// name information. void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; } bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; } - + //===--------------------------------------------------------------------===// // Block Manipulation //===--------------------------------------------------------------------===// @@ -95,7 +95,7 @@ public: /// block info block for this Bitstream. We only process it for the first /// cursor that walks over it. bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } - + /// getBlockInfo - If there is block info for the specified ID, return it, /// otherwise return null. const BlockInfo *getBlockInfo(unsigned BlockID) const { @@ -126,74 +126,74 @@ class BitstreamCursor { friend class Deserializer; BitstreamReader *BitStream; size_t NextChar; - + /// CurWord - This is the current data we have pulled from the stream but have /// not returned to the client. uint32_t CurWord; - + /// BitsInCurWord - This is the number of bits in CurWord that are valid. This /// is always from [0...31] inclusive. unsigned BitsInCurWord; - + // CurCodeSize - This is the declared size of code values used for the current // block, in bits. unsigned CurCodeSize; - + /// CurAbbrevs - Abbrevs installed at in this block. std::vector<BitCodeAbbrev*> CurAbbrevs; - + struct Block { unsigned PrevCodeSize; std::vector<BitCodeAbbrev*> PrevAbbrevs; explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} }; - + /// BlockScope - This tracks the codesize of parent blocks. SmallVector<Block, 8> BlockScope; - + public: BitstreamCursor() : BitStream(0), NextChar(0) { } BitstreamCursor(const BitstreamCursor &RHS) : BitStream(0), NextChar(0) { operator=(RHS); } - + explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) { NextChar = 0; CurWord = 0; BitsInCurWord = 0; CurCodeSize = 2; } - + void init(BitstreamReader &R) { freeState(); - + BitStream = &R; NextChar = 0; CurWord = 0; BitsInCurWord = 0; CurCodeSize = 2; } - + ~BitstreamCursor() { freeState(); } - + void operator=(const BitstreamCursor &RHS) { freeState(); - + BitStream = RHS.BitStream; NextChar = RHS.NextChar; CurWord = RHS.CurWord; BitsInCurWord = RHS.BitsInCurWord; CurCodeSize = RHS.CurCodeSize; - + // Copy abbreviations, and bump ref counts. CurAbbrevs = RHS.CurAbbrevs; for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size()); i != e; ++i) CurAbbrevs[i]->addRef(); - + // Copy block scope and bump ref counts. BlockScope = RHS.BlockScope; for (unsigned S = 0, e = static_cast<unsigned>(BlockScope.size()); @@ -204,14 +204,14 @@ public: Abbrevs[i]->addRef(); } } - + void freeState() { // Free all the Abbrevs. for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size()); i != e; ++i) CurAbbrevs[i]->dropRef(); CurAbbrevs.clear(); - + // Free all the Abbrevs in the block scope. for (unsigned S = 0, e = static_cast<unsigned>(BlockScope.size()); S != e; ++S) { @@ -222,10 +222,10 @@ public: } BlockScope.clear(); } - + /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. unsigned GetAbbrevIDWidth() const { return CurCodeSize; } - + bool isEndPos(size_t pos) { return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); } @@ -255,37 +255,37 @@ public: bool AtEndOfStream() { return isEndPos(NextChar) && BitsInCurWord == 0; } - + /// GetCurrentBitNo - Return the bit # of the bit we are reading. uint64_t GetCurrentBitNo() const { return NextChar*CHAR_BIT - BitsInCurWord; } - + BitstreamReader *getBitStreamReader() { return BitStream; } const BitstreamReader *getBitStreamReader() const { return BitStream; } - - + + /// JumpToBit - Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; uintptr_t WordBitNo = uintptr_t(BitNo) & 31; assert(canSkipToPos(ByteNo) && "Invalid location"); - + // Move the cursor to the right word. NextChar = ByteNo; BitsInCurWord = 0; CurWord = 0; - + // Skip over any bits that are already consumed. if (WordBitNo) Read(static_cast<unsigned>(WordBitNo)); } - - + + uint32_t Read(unsigned NumBits) { assert(NumBits <= 32 && "Cannot return more than 32 bits!"); // If the field is fully contained by CurWord, return it quickly. @@ -409,7 +409,7 @@ public: } /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter - /// the block, and return true if the block is valid. + /// the block, and return true if the block has an error. bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0) { // Save the current block's state on BlockScope. BlockScope.push_back(Block(CurCodeSize)); @@ -473,7 +473,7 @@ private: // If the abbrev specifies the literal value to use, use it. Vals.push_back(Op.getLiteralValue()); } - + void ReadAbbreviatedField(const BitCodeAbbrevOp &Op, SmallVectorImpl<uint64_t> &Vals) { assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); @@ -494,13 +494,13 @@ private: } public: - /// getAbbrev - Return the abbreviation for the specified AbbrevId. + /// getAbbrev - Return the abbreviation for the specified AbbrevId. const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); return CurAbbrevs[AbbrevNo]; } - + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, const char **BlobStart = 0, unsigned *BlobLen = 0) { if (AbbrevID == bitc::UNABBREV_RECORD) { @@ -516,7 +516,7 @@ public: for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); if (Op.isLiteral()) { - ReadAbbreviatedLiteral(Op, Vals); + ReadAbbreviatedLiteral(Op, Vals); } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { // Array case. Read the number of elements as a vbr6. unsigned NumElts = ReadVBR(6); @@ -535,7 +535,7 @@ public: // Figure out where the end of this blob will be including tail padding. size_t NewEnd = NextChar+((NumElts+3)&~3); - + // If this would read off the end of the bitcode file, just set the // record to empty and return. if (!canSkipToPos(NewEnd)) { @@ -543,7 +543,7 @@ public: NextChar = BitStream->getBitcodeBytes().getExtent(); break; } - + // Otherwise, read the number of bytes. If we can return a reference to // the data, do so to avoid copying it. if (BlobStart) { @@ -571,7 +571,7 @@ public: return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen); } - + //===--------------------------------------------------------------------===// // Abbrev Processing //===--------------------------------------------------------------------===// @@ -594,14 +594,14 @@ public: } CurAbbrevs.push_back(Abbv); } - + public: bool ReadBlockInfoBlock() { // If this is the second stream to get to the block info block, skip it. if (BitStream->hasBlockInfoRecords()) return SkipBlock(); - + if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; SmallVector<uint64_t, 64> Record; @@ -662,7 +662,7 @@ public: } } }; - + } // End llvm namespace #endif diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index dea118f..1021fbd 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -15,8 +15,8 @@ #ifndef BITSTREAM_WRITER_H #define BITSTREAM_WRITER_H -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitCodes.h" #include <vector> @@ -273,7 +273,7 @@ public: private: /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev - /// record. This is a no-op, since the abbrev specifies the literal to use. + /// record. This is a no-op, since the abbrev specifies the literal to use. template<typename uintty> void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) { assert(Op.isLiteral() && "Not a literal"); @@ -282,13 +282,13 @@ private: assert(V == Op.getLiteralValue() && "Invalid abbrev for record!"); } - + /// EmitAbbreviatedField - Emit a single scalar field value with the specified /// encoding. template<typename uintty> void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!"); - + // Encode the value as we are commanded. switch (Op.getEncoding()) { default: llvm_unreachable("Unknown encoding!"); @@ -305,7 +305,7 @@ private: break; } } - + /// EmitRecordWithAbbrevImpl - This is the core implementation of the record /// emission code. If BlobData is non-null, then it specifies an array of /// data that should be emitted as part of the Blob or Array operand that is @@ -341,11 +341,11 @@ private: "Blob data and record entries specified for array!"); // Emit a vbr6 to indicate the number of elements present. EmitVBR(static_cast<uint32_t>(BlobLen), 6); - + // Emit each field. for (unsigned i = 0; i != BlobLen; ++i) EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]); - + // Know that blob data is consumed for assertion below. BlobData = 0; } else { @@ -359,7 +359,7 @@ private: } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { // If this record has blob data, emit it, otherwise we must have record // entries to encode this way. - + // Emit a vbr6 to indicate the number of elements present. if (BlobData) { EmitVBR(static_cast<uint32_t>(BlobLen), 6); @@ -368,7 +368,7 @@ private: } else { EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6); } - + // Flush to a 32-bit alignment boundary. FlushToWord(); @@ -376,7 +376,7 @@ private: if (BlobData) { for (unsigned i = 0; i != BlobLen; ++i) WriteByte((unsigned char)BlobData[i]); - + // Know that blob data is consumed for assertion below. BlobData = 0; } else { @@ -399,7 +399,7 @@ private: assert(BlobData == 0 && "Blob data specified for record that doesn't use it!"); } - + public: /// EmitRecord - Emit the specified record to the stream, using an abbrev if @@ -420,10 +420,10 @@ public: // Insert the code into Vals to treat it uniformly. Vals.insert(Vals.begin(), Code); - + EmitRecordWithAbbrev(Abbrev, Vals); } - + /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation. /// Unlike EmitRecord, the code for the record should be included in Vals as /// the first entry. @@ -431,7 +431,7 @@ public: void EmitRecordWithAbbrev(unsigned Abbrev, SmallVectorImpl<uintty> &Vals) { EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef()); } - + /// EmitRecordWithBlob - Emit the specified record to the stream, using an /// abbrev that includes a blob at the end. The blob data to emit is /// specified by the pointer and length specified at the end. In contrast to @@ -461,7 +461,7 @@ public: return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData, ArrayLen)); } - + //===--------------------------------------------------------------------===// // Abbrev Emission //===--------------------------------------------------------------------===// diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index c1dc190..601777d 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -31,16 +31,16 @@ namespace bitc { PARAMATTR_BLOCK_ID, UNUSED_ID1, - + CONSTANTS_BLOCK_ID, FUNCTION_BLOCK_ID, - + UNUSED_ID2, - + VALUE_SYMTAB_BLOCK_ID, METADATA_BLOCK_ID, METADATA_ATTACHMENT_ID, - + TYPE_BLOCK_ID_NEW, USELIST_BLOCK_ID @@ -54,6 +54,8 @@ namespace bitc { MODULE_CODE_DATALAYOUT = 3, // DATALAYOUT: [strchr x N] MODULE_CODE_ASM = 4, // ASM: [strchr x N] MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N] + + // FIXME: Remove DEPLIB in 4.0. MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N] // GLOBALVAR: [pointer type, isconst, initid, @@ -93,9 +95,9 @@ namespace bitc { TYPE_CODE_FUNCTION_OLD = 9, // FUNCTION: [vararg, attrid, retty, // paramty x N] - + TYPE_CODE_HALF = 10, // HALF - + TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty] TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty] @@ -109,7 +111,7 @@ namespace bitc { TYPE_CODE_METADATA = 16, // METADATA TYPE_CODE_X86_MMX = 17, // X86 MMX - + TYPE_CODE_STRUCT_ANON = 18, // STRUCT_ANON: [ispacked, eltty x N] TYPE_CODE_STRUCT_NAME = 19, // STRUCT_NAME: [strchr x N] TYPE_CODE_STRUCT_NAMED = 20,// STRUCT_NAMED: [ispacked, eltty x N] @@ -234,7 +236,7 @@ namespace bitc { OBO_NO_SIGNED_WRAP = 1 }; - /// PossiblyExactOperatorOptionalFlags - Flags for serializing + /// PossiblyExactOperatorOptionalFlags - Flags for serializing /// PossiblyExactOperator's SubclassOptionalData contents. enum PossiblyExactOperatorOptionalFlags { PEO_EXACT = 0 diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt index f8cb425..32ffca7 100644 --- a/include/llvm/CMakeLists.txt +++ b/include/llvm/CMakeLists.txt @@ -1,10 +1,4 @@ -set(LLVM_TARGET_DEFINITIONS Intrinsics.td) - -tablegen(LLVM Intrinsics.gen -gen-intrinsic) - -add_custom_target(intrinsics_gen ALL - DEPENDS ${llvm_builded_incs_dir}/Intrinsics.gen) -set_target_properties(intrinsics_gen PROPERTIES FOLDER "Tablegenning") +add_subdirectory(IR) if( MSVC_IDE OR XCODE ) # Creates a dummy target containing all headers for the benefit of diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index 0b609ed..81e75d8 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -14,12 +14,12 @@ #ifndef LLVM_CODEGEN_ANALYSIS_H #define LLVM_CODEGEN_ANALYSIS_H -#include "llvm/Instructions.h" -#include "llvm/InlineAsm.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/CallSite.h" namespace llvm { @@ -86,12 +86,9 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); /// between it and the return. /// /// This function only tests target-independent requirements. -bool isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, +bool isInTailCallPosition(ImmutableCallSite CS, Attribute CalleeRetAttr, const TargetLowering &TLI); -bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, - SDValue &Chain, const TargetLowering &TLI); - } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 2920675..e0a6e3f 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -17,7 +17,7 @@ #define LLVM_CODEGEN_ASMPRINTER_H #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/InlineAsm.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -48,7 +48,7 @@ namespace llvm { class DwarfException; class Mangler; class TargetLoweringObjectFile; - class TargetData; + class DataLayout; class TargetMachine; /// AsmPrinter - This class is intended to be used as a driving class for all @@ -131,8 +131,8 @@ namespace llvm { /// getObjFileLowering - Return information about object file lowering. const TargetLoweringObjectFile &getObjFileLowering() const; - /// getTargetData - Return information about data layout. - const TargetData &getTargetData() const; + /// getDataLayout - Return information about data layout. + const DataLayout &getDataLayout() const; /// getCurrentSection() - Return the current section we are emitting to. const MCSection *getCurrentSection() const; @@ -385,10 +385,8 @@ namespace llvm { /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. unsigned GetSizeOfEncodedValue(unsigned Encoding) const; - /// EmitReference - Emit a reference to a label with a specified encoding. - /// - void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; - void EmitReference(const GlobalValue *GV, unsigned Encoding) const; + /// EmitReference - Emit reference to a ttype global with a specified encoding. + void EmitTTypeReference(const GlobalValue *GV, unsigned Encoding) const; /// EmitSectionOffset - Emit the 4-byte offset of Label from the start of /// its section. This can be done with a special directive if the target diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index 2f76a6c..9cd2dec 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -11,8 +11,8 @@ #ifndef LLVM_CODEGEN_CALCSPILLWEIGHTS_H #define LLVM_CODEGEN_CALCSPILLWEIGHTS_H -#include "llvm/CodeGen/SlotIndexes.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/SlotIndexes.h" namespace llvm { diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index 3afe309..c035e07 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -16,10 +16,11 @@ #define LLVM_CODEGEN_CALLINGCONVLOWER_H #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/CallingConv.h" #include "llvm/Target/TargetCallingConv.h" -#include "llvm/CallingConv.h" namespace llvm { class TargetRegisterInfo; @@ -49,10 +50,10 @@ private: unsigned Loc; /// isMem - True if this is a memory loc, false if it is a register loc. - bool isMem : 1; + unsigned isMem : 1; /// isCustom - True if this arg/retval requires special handling. - bool isCustom : 1; + unsigned isCustom : 1; /// Information about how the value is assigned. LocInfo HTP : 6; @@ -288,6 +289,7 @@ public: StackOffset = ((StackOffset + Align-1) & ~(Align-1)); unsigned Result = StackOffset; StackOffset += Size; + MF.getFrameInfo()->ensureMaxAlignment(Align); return Result; } diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h new file mode 100644 index 0000000..a66e05b --- /dev/null +++ b/include/llvm/CodeGen/CommandFlags.h @@ -0,0 +1,227 @@ +//===-- CommandFlags.h - Command Line Flags 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 contains codegen-specific flags that are shared between different +// command line tools. The tools "llc" and "opt" both use this file to prevent +// flag duplication. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_COMMAND_LINE_FLAGS_H +#define LLVM_CODEGEN_COMMAND_LINE_FLAGS_H + +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetMachine.h" +#include <string> +using namespace llvm; + +cl::opt<std::string> +MArch("march", cl::desc("Architecture to generate code for (see --version)")); + +cl::opt<std::string> +MCPU("mcpu", + cl::desc("Target a specific cpu type (-mcpu=help for details)"), + cl::value_desc("cpu-name"), + cl::init("")); + +cl::list<std::string> +MAttrs("mattr", + cl::CommaSeparated, + cl::desc("Target specific attributes (-mattr=help for details)"), + cl::value_desc("a1,+a2,-a3,...")); + +cl::opt<Reloc::Model> +RelocModel("relocation-model", + cl::desc("Choose relocation model"), + cl::init(Reloc::Default), + cl::values( + clEnumValN(Reloc::Default, "default", + "Target default relocation model"), + clEnumValN(Reloc::Static, "static", + "Non-relocatable code"), + clEnumValN(Reloc::PIC_, "pic", + "Fully relocatable, position independent code"), + clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic", + "Relocatable external references, non-relocatable code"), + clEnumValEnd)); + +cl::opt<llvm::CodeModel::Model> +CMModel("code-model", + cl::desc("Choose code model"), + cl::init(CodeModel::Default), + cl::values(clEnumValN(CodeModel::Default, "default", + "Target default code model"), + clEnumValN(CodeModel::Small, "small", + "Small code model"), + clEnumValN(CodeModel::Kernel, "kernel", + "Kernel code model"), + clEnumValN(CodeModel::Medium, "medium", + "Medium code model"), + clEnumValN(CodeModel::Large, "large", + "Large code model"), + clEnumValEnd)); + +cl::opt<bool> +RelaxAll("mc-relax-all", + cl::desc("When used with filetype=obj, " + "relax all fixups in the emitted object file")); + +cl::opt<TargetMachine::CodeGenFileType> +FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), + cl::desc("Choose a file type (not all types are supported by all targets):"), + cl::values( + clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm", + "Emit an assembly ('.s') file"), + clEnumValN(TargetMachine::CGFT_ObjectFile, "obj", + "Emit a native object ('.o') file"), + clEnumValN(TargetMachine::CGFT_Null, "null", + "Emit nothing, for performance testing"), + clEnumValEnd)); + +cl::opt<bool> DisableDotLoc("disable-dot-loc", cl::Hidden, + cl::desc("Do not use .loc entries")); + +cl::opt<bool> DisableCFI("disable-cfi", cl::Hidden, + cl::desc("Do not use .cfi_* directives")); + +cl::opt<bool> EnableDwarfDirectory("enable-dwarf-directory", cl::Hidden, + cl::desc("Use .file directives with an explicit directory.")); + +cl::opt<bool> +DisableRedZone("disable-red-zone", + cl::desc("Do not emit code that uses the red zone."), + cl::init(false)); + +cl::opt<bool> +EnableFPMAD("enable-fp-mad", + cl::desc("Enable less precise MAD instructions to be generated"), + cl::init(false)); + +cl::opt<bool> +DisableFPElim("disable-fp-elim", + cl::desc("Disable frame pointer elimination optimization"), + cl::init(false)); + +cl::opt<bool> +DisableFPElimNonLeaf("disable-non-leaf-fp-elim", + cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"), + cl::init(false)); + +cl::opt<bool> +EnableUnsafeFPMath("enable-unsafe-fp-math", + cl::desc("Enable optimizations that may decrease FP precision"), + cl::init(false)); + +cl::opt<bool> +EnableNoInfsFPMath("enable-no-infs-fp-math", + cl::desc("Enable FP math optimizations that assume no +-Infs"), + cl::init(false)); + +cl::opt<bool> +EnableNoNaNsFPMath("enable-no-nans-fp-math", + cl::desc("Enable FP math optimizations that assume no NaNs"), + cl::init(false)); + +cl::opt<bool> +EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", + cl::Hidden, + cl::desc("Force codegen to assume rounding mode can change dynamically"), + cl::init(false)); + +cl::opt<bool> +GenerateSoftFloatCalls("soft-float", + cl::desc("Generate software floating point library calls"), + cl::init(false)); + +cl::opt<llvm::FloatABI::ABIType> +FloatABIForCalls("float-abi", + cl::desc("Choose float ABI type"), + cl::init(FloatABI::Default), + cl::values( + clEnumValN(FloatABI::Default, "default", + "Target default float ABI type"), + clEnumValN(FloatABI::Soft, "soft", + "Soft float ABI (implied by -soft-float)"), + clEnumValN(FloatABI::Hard, "hard", + "Hard float ABI (uses FP registers)"), + clEnumValEnd)); + +cl::opt<llvm::FPOpFusion::FPOpFusionMode> +FuseFPOps("fp-contract", + cl::desc("Enable aggresive formation of fused FP ops"), + cl::init(FPOpFusion::Standard), + cl::values( + clEnumValN(FPOpFusion::Fast, "fast", + "Fuse FP ops whenever profitable"), + clEnumValN(FPOpFusion::Standard, "on", + "Only fuse 'blessed' FP ops."), + clEnumValN(FPOpFusion::Strict, "off", + "Only fuse FP ops when the result won't be effected."), + clEnumValEnd)); + +cl::opt<bool> +DontPlaceZerosInBSS("nozero-initialized-in-bss", + cl::desc("Don't place zero-initialized symbols into bss section"), + cl::init(false)); + +cl::opt<bool> +EnableGuaranteedTailCallOpt("tailcallopt", + cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."), + cl::init(false)); + +cl::opt<bool> +DisableTailCalls("disable-tail-calls", + cl::desc("Never emit tail calls"), + cl::init(false)); + +cl::opt<unsigned> +OverrideStackAlignment("stack-alignment", + cl::desc("Override default stack alignment"), + cl::init(0)); + +cl::opt<bool> +EnableRealignStack("realign-stack", + cl::desc("Realign stack if needed"), + cl::init(true)); + +cl::opt<std::string> +TrapFuncName("trap-func", cl::Hidden, + cl::desc("Emit a call to trap function rather than a trap instruction"), + cl::init("")); + +cl::opt<bool> +EnablePIE("enable-pie", + cl::desc("Assume the creation of a position independent executable."), + cl::init(false)); + +cl::opt<bool> +SegmentedStacks("segmented-stacks", + cl::desc("Use segmented stacks if possible."), + cl::init(false)); + +cl::opt<bool> +UseInitArray("use-init-array", + cl::desc("Use .init_array instead of .ctors."), + cl::init(false)); + +cl::opt<std::string> StopAfter("stop-after", + cl::desc("Stop compilation after a specific pass"), + cl::value_desc("pass-name"), + cl::init("")); +cl::opt<std::string> StartAfter("start-after", + cl::desc("Resume compilation after a specific pass"), + cl::value_desc("pass-name"), + cl::init("")); + +cl::opt<unsigned> +SSPBufferSize("stack-protector-buffer-size", cl::init(8), + cl::desc("Lower bound for a buffer to be considered for " + "stack protection")); +#endif diff --git a/include/llvm/CodeGen/DAGCombine.h b/include/llvm/CodeGen/DAGCombine.h new file mode 100644 index 0000000..8b59190 --- /dev/null +++ b/include/llvm/CodeGen/DAGCombine.h @@ -0,0 +1,25 @@ +//===-- llvm/CodeGen/DAGCombine.h ------- SelectionDAG Nodes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// + +#ifndef LLVM_CODEGEN_DAGCOMBINE_H +#define LLVM_CODEGEN_DAGCOMBINE_H + +namespace llvm { + +enum CombineLevel { + BeforeLegalizeTypes, + AfterLegalizeTypes, + AfterLegalizeVectorOps, + AfterLegalizeDAG +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h index 2d2db78..9d25fd3 100644 --- a/include/llvm/CodeGen/DFAPacketizer.h +++ b/include/llvm/CodeGen/DFAPacketizer.h @@ -26,8 +26,8 @@ #ifndef LLVM_CODEGEN_DFAPACKETIZER_H #define LLVM_CODEGEN_DFAPACKETIZER_H -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include <map> namespace llvm { @@ -135,7 +135,7 @@ public: // initPacketizerState - perform initialization before packetizing // an instruction. This function is supposed to be overrided by // the target dependent packetizer. - virtual void initPacketizerState(void) { return; } + virtual void initPacketizerState() { return; } // ignorePseudoInstruction - Ignore bundling of pseudo instructions. virtual bool ignorePseudoInstruction(MachineInstr *I, diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 7cb9695..0561905 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -15,8 +15,8 @@ #define LLVM_CODEGEN_FASTISEL_H #include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/ValueTypes.h" namespace llvm { @@ -32,7 +32,7 @@ class MachineFunction; class MachineInstr; class MachineFrameInfo; class MachineRegisterInfo; -class TargetData; +class DataLayout; class TargetInstrInfo; class TargetLibraryInfo; class TargetLowering; @@ -54,7 +54,7 @@ protected: MachineConstantPool &MCP; DebugLoc DL; const TargetMachine &TM; - const TargetData &TD; + const DataLayout &TD; const TargetInstrInfo &TII; const TargetLowering &TLI; const TargetRegisterInfo &TRI; @@ -131,6 +131,10 @@ public: /// into the current block. void recomputeInsertPt(); + /// removeDeadCode - Remove all dead instructions between the I and E. + void removeDeadCode(MachineBasicBlock::iterator I, + MachineBasicBlock::iterator E); + struct SavePoint { MachineBasicBlock::iterator InsertPt; DebugLoc DL; @@ -395,10 +399,6 @@ private: /// hasTrivialKill - Test whether the given value has exactly one use. bool hasTrivialKill(const Value *V) const; - - /// removeDeadCode - Remove all dead instructions between the I and E. - void removeDeadCode(MachineBasicBlock::iterator I, - MachineBasicBlock::iterator E); }; } diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 8cf22ec..72e0937 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -15,8 +15,6 @@ #ifndef LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H #define LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H -#include "llvm/InlineAsm.h" -#include "llvm/Instructions.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" @@ -24,9 +22,11 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/BranchProbabilityInfo.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/CallSite.h" #include "llvm/Target/TargetRegisterInfo.h" #include <vector> @@ -136,7 +136,7 @@ public: return ValueMap.count(V); } - unsigned CreateReg(EVT VT); + unsigned CreateReg(MVT VT); unsigned CreateRegs(Type *Ty); diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index 20e33f7..fa40049 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -33,9 +33,9 @@ #ifndef LLVM_CODEGEN_GCMETADATA_H #define LLVM_CODEGEN_GCMETADATA_H -#include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Pass.h" #include "llvm/Support/DebugLoc.h" namespace llvm { @@ -122,6 +122,11 @@ namespace llvm { Roots.push_back(GCRoot(Num, Metadata)); } + /// removeStackRoot - Removes a root. + roots_iterator removeStackRoot(roots_iterator position) { + return Roots.erase(position); + } + /// addSafePoint - Notes the existence of a safe point. Num is the ID of the /// label just prior to the safe point (if the code generator is using /// MachineModuleInfo). diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 17a2653..4a6b5ac 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -48,9 +48,10 @@ namespace llvm { // May only be subclassed. GCMetadataPrinter(); - // Do not implement. - GCMetadataPrinter(const GCMetadataPrinter &); - GCMetadataPrinter &operator=(const GCMetadataPrinter &); + private: + GCMetadataPrinter(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; + GCMetadataPrinter & + operator=(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; public: GCStrategy &getStrategy() { return *S; } diff --git a/include/llvm/CodeGen/IntrinsicLowering.h b/include/llvm/CodeGen/IntrinsicLowering.h index 767b666..68389dd 100644 --- a/include/llvm/CodeGen/IntrinsicLowering.h +++ b/include/llvm/CodeGen/IntrinsicLowering.h @@ -16,20 +16,20 @@ #ifndef LLVM_CODEGEN_INTRINSICLOWERING_H #define LLVM_CODEGEN_INTRINSICLOWERING_H -#include "llvm/Intrinsics.h" +#include "llvm/IR/Intrinsics.h" namespace llvm { class CallInst; class Module; - class TargetData; + class DataLayout; class IntrinsicLowering { - const TargetData& TD; + const DataLayout& TD; bool Warned; public: - explicit IntrinsicLowering(const TargetData &td) : + explicit IntrinsicLowering(const DataLayout &td) : TD(td), Warned(false) {} /// AddPrototypes - This method, if called, causes all of the prototypes diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h index 89f00e9..21a3f48 100644 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ b/include/llvm/CodeGen/JITCodeEmitter.h @@ -17,11 +17,11 @@ #ifndef LLVM_CODEGEN_JITCODEEMITTER_H #define LLVM_CODEGEN_JITCODEEMITTER_H -#include <string> +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/ADT/DenseMap.h" +#include <string> namespace llvm { diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 8414c64..3cb6b4d 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -17,11 +17,11 @@ #ifndef LLVM_CODEGEN_LEXICALSCOPES_H #define LLVM_CODEGEN_LEXICALSCOPES_H -#include "llvm/Metadata.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/DebugLoc.h" #include "llvm/Support/ValueHandle.h" #include <utility> diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 46dd004..2145eb8 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -15,9 +15,9 @@ #ifndef LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H #define LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H +#include "llvm/CodeGen/GCs.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/CodeGen/GCs.h" #include "llvm/Target/TargetMachine.h" #include <cstdlib> diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 5aeb1a8..9576075 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -22,9 +22,9 @@ #define LLVM_CODEGEN_LIVEINTERVAL_H #include "llvm/ADT/IntEqClasses.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/AlignOf.h" #include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Allocator.h" #include <cassert> #include <climits> @@ -114,9 +114,6 @@ namespace llvm { void dump() const; void print(raw_ostream &os) const; - - private: - LiveRange(); // DO NOT IMPLEMENT }; template <> struct isPodLike<LiveRange> { static const bool value = true; }; @@ -276,11 +273,6 @@ namespace llvm { void MergeValueInAsValue(const LiveInterval &RHS, const VNInfo *RHSValNo, VNInfo *LHSValNo); - /// Copy - Copy the specified live interval. This copies all the fields - /// except for the register of the interval. - void Copy(const LiveInterval &RHS, MachineRegisterInfo *MRI, - VNInfo::Allocator &VNInfoAllocator); - bool empty() const { return ranges.empty(); } /// beginIndex - Return the lowest numbered slot covered by interval. @@ -313,12 +305,6 @@ namespace llvm { return r != end() && r->end == index; } - /// killedInRange - Return true if the interval has kills in [Start,End). - /// Note that the kill point is considered the end of a live range, so it is - /// not contained in the live range. If a live range ends at End, it won't - /// be counted as a kill by this method. - bool killedInRange(SlotIndex Start, SlotIndex End) const; - /// getLiveRangeContaining - Return the live range that contains the /// specified index, or null if there is none. const LiveRange *getLiveRangeContaining(SlotIndex Idx) const { @@ -478,7 +464,7 @@ namespace llvm { VNInfo *LHSValNo = 0, const VNInfo *RHSValNo = 0); - LiveInterval& operator=(const LiveInterval& rhs); // DO NOT IMPLEMENT + LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; }; @@ -510,7 +496,9 @@ namespace llvm { if (I == E) return; // Is this an instruction live-in segment? - if (SlotIndex::isEarlierInstr(I->start, Idx)) { + // 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. @@ -519,6 +507,12 @@ namespace llvm { 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. diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index bf74690..9e89519 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -20,16 +20,16 @@ #ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H #define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/CodeGen/SlotIndexes.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/SlotIndexes.h" #include "llvm/Support/Allocator.h" +#include "llvm/Target/TargetRegisterInfo.h" #include <cmath> #include <iterator> @@ -65,12 +65,6 @@ namespace llvm { /// Live interval pointers for all the virtual registers. IndexedMap<LiveInterval*, VirtReg2IndexFunctor> VirtRegIntervals; - /// AllocatableRegs - A bit vector of allocatable registers. - BitVector AllocatableRegs; - - /// ReservedRegs - A bit vector of reserved registers. - BitVector ReservedRegs; - /// RegMaskSlots - Sorted list of instructions with register mask operands. /// Always use the 'r' slot, RegMasks are normal clobbers, not early /// clobbers. @@ -123,18 +117,6 @@ namespace llvm { return VirtRegIntervals.inBounds(Reg) && VirtRegIntervals[Reg]; } - /// isAllocatable - is the physical register reg allocatable in the current - /// function? - bool isAllocatable(unsigned reg) const { - return AllocatableRegs.test(reg); - } - - /// isReserved - is the physical register reg reserved in the current - /// function - bool isReserved(unsigned reg) const { - return ReservedRegs.test(reg); - } - // Interval creation. LiveInterval &getOrCreateInterval(unsigned Reg) { if (!hasInterval(Reg)) { @@ -165,6 +147,26 @@ namespace llvm { bool shrinkToUses(LiveInterval *li, SmallVectorImpl<MachineInstr*> *dead = 0); + /// extendToIndices - Extend the live range of LI to reach all points in + /// Indices. The points in the Indices array must be jointly dominated by + /// existing defs in LI. PHI-defs are added as needed to maintain SSA form. + /// + /// If a SlotIndex in Indices is the end index of a basic block, LI will be + /// extended to be live out of the basic block. + /// + /// See also LiveRangeCalc::extend(). + void extendToIndices(LiveInterval *LI, 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 + /// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the + /// value's live range. + /// + /// Calling pruneValue() and extendToIndices() can be used to reconstruct + /// SSA form after adding defs to a virtual register. + void pruneValue(LiveInterval *LI, SlotIndex Kill, + SmallVectorImpl<SlotIndex> *EndPoints); + SlotIndexes *getSlotIndexes() const { return Indexes; } @@ -258,15 +260,20 @@ namespace llvm { /// instruction 'mi' has been moved within a basic block. This will update /// the live intervals for all operands of mi. Moves between basic blocks /// are not supported. - void handleMove(MachineInstr* MI); + /// + /// \param UpdateFlags Update live intervals for nonallocatable physregs. + void handleMove(MachineInstr* MI, bool UpdateFlags = false); /// moveIntoBundle - Update intervals for operands of MI so that they /// begin/end on the SlotIndex for BundleStart. /// + /// \param UpdateFlags Update live intervals for nonallocatable physregs. + /// /// Requires MI and BundleStart to have SlotIndexes, and assumes /// existing liveness is accurate. BundleStart should be the first /// instruction in the Bundle. - void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart); + void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart, + bool UpdateFlags = false); // Register mask functions. // @@ -340,6 +347,10 @@ namespace llvm { return RegUnitIntervals[Unit]; } + const LiveInterval *getCachedRegUnit(unsigned Unit) const { + return RegUnitIntervals[Unit]; + } + private: /// computeIntervals - Compute live intervals. void computeIntervals(); diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h new file mode 100644 index 0000000..6a61614 --- /dev/null +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -0,0 +1,205 @@ +//===-- LiveIntervalUnion.h - Live interval union data struct --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LiveIntervalUnion is a union of live segments across multiple live virtual +// registers. This may be used during coalescing to represent a congruence +// class, or during register allocation to model liveness of a physical +// register. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVALUNION +#define LLVM_CODEGEN_LIVEINTERVALUNION + +#include "llvm/ADT/IntervalMap.h" +#include "llvm/CodeGen/LiveInterval.h" + +namespace llvm { + +class TargetRegisterInfo; + +#ifndef NDEBUG +// forward declaration +template <unsigned Element> class SparseBitVector; +typedef SparseBitVector<128> LiveVirtRegBitSet; +#endif + +/// Compare a live virtual register segment to a LiveIntervalUnion segment. +inline bool +overlap(const LiveRange &VRSeg, + const IntervalMap<SlotIndex, LiveInterval*>::const_iterator &LUSeg) { + return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end; +} + +/// Union of live intervals that are strong candidates for coalescing into a +/// single register (either physical or virtual depending on the context). We +/// expect the constituent live intervals to be disjoint, although we may +/// eventually make exceptions to handle value-based interference. +class LiveIntervalUnion { + // A set of live virtual register segments that supports fast insertion, + // intersection, and removal. + // Mapping SlotIndex intervals to virtual register numbers. + typedef IntervalMap<SlotIndex, LiveInterval*> LiveSegments; + +public: + // SegmentIter can advance to the next segment ordered by starting position + // which may belong to a different live virtual register. We also must be able + // to reach the current segment's containing virtual register. + typedef LiveSegments::iterator SegmentIter; + + // LiveIntervalUnions share an external allocator. + typedef LiveSegments::Allocator Allocator; + + class Query; + +private: + unsigned Tag; // unique tag for current contents. + LiveSegments Segments; // union of virtual reg segments + +public: + explicit LiveIntervalUnion(Allocator &a) : Tag(0), Segments(a) {} + + // Iterate over all segments in the union of live virtual registers ordered + // by their starting position. + SegmentIter begin() { return Segments.begin(); } + SegmentIter end() { return Segments.end(); } + SegmentIter find(SlotIndex x) { return Segments.find(x); } + bool empty() const { return Segments.empty(); } + SlotIndex startIndex() const { return Segments.start(); } + + // Provide public access to the underlying map to allow overlap iteration. + typedef LiveSegments Map; + const Map &getMap() { return Segments; } + + /// getTag - Return an opaque tag representing the current state of the union. + unsigned getTag() const { return Tag; } + + /// changedSince - Return true if the union change since getTag returned tag. + bool changedSince(unsigned tag) const { return tag != Tag; } + + // Add a live virtual register to this union and merge its segments. + void unify(LiveInterval &VirtReg); + + // Remove a live virtual register's segments from this union. + void extract(LiveInterval &VirtReg); + + // Remove all inserted virtual registers. + void clear() { Segments.clear(); ++Tag; } + + // Print union, using TRI to translate register names + void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const; + +#ifndef NDEBUG + // Verify the live intervals in this union and add them to the visited set. + void verify(LiveVirtRegBitSet& VisitedVRegs); +#endif + + /// Query interferences between a single live virtual register and a live + /// interval union. + class Query { + LiveIntervalUnion *LiveUnion; + LiveInterval *VirtReg; + LiveInterval::iterator VirtRegI; // current position in VirtReg + SegmentIter LiveUnionI; // current position in LiveUnion + SmallVector<LiveInterval*,4> InterferingVRegs; + bool CheckedFirstInterference; + bool SeenAllInterferences; + bool SeenUnspillableVReg; + unsigned Tag, UserTag; + + public: + Query(): LiveUnion(), VirtReg(), Tag(0), UserTag(0) {} + + Query(LiveInterval *VReg, LiveIntervalUnion *LIU): + LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false), + SeenAllInterferences(false), SeenUnspillableVReg(false) + {} + + void clear() { + LiveUnion = NULL; + VirtReg = NULL; + InterferingVRegs.clear(); + CheckedFirstInterference = false; + SeenAllInterferences = false; + SeenUnspillableVReg = false; + Tag = 0; + UserTag = 0; + } + + void init(unsigned UTag, LiveInterval *VReg, LiveIntervalUnion *LIU) { + assert(VReg && LIU && "Invalid arguments"); + if (UserTag == UTag && VirtReg == VReg && + LiveUnion == LIU && !LIU->changedSince(Tag)) { + // Retain cached results, e.g. firstInterference. + return; + } + clear(); + LiveUnion = LIU; + VirtReg = VReg; + Tag = LIU->getTag(); + UserTag = UTag; + } + + LiveInterval &virtReg() const { + assert(VirtReg && "uninitialized"); + return *VirtReg; + } + + // Does this live virtual register interfere with the union? + bool checkInterference() { return collectInterferingVRegs(1); } + + // Count the virtual registers in this union that interfere with this + // query's live virtual register, up to maxInterferingRegs. + unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX); + + // Was this virtual register visited during collectInterferingVRegs? + bool isSeenInterference(LiveInterval *VReg) const; + + // Did collectInterferingVRegs collect all interferences? + bool seenAllInterferences() const { return SeenAllInterferences; } + + // Did collectInterferingVRegs encounter an unspillable vreg? + bool seenUnspillableVReg() const { return SeenUnspillableVReg; } + + // Vector generated by collectInterferingVRegs. + const SmallVectorImpl<LiveInterval*> &interferingVRegs() const { + return InterferingVRegs; + } + + private: + Query(const Query&) LLVM_DELETED_FUNCTION; + void operator=(const Query&) LLVM_DELETED_FUNCTION; + }; + + // Array of LiveIntervalUnions. + class Array { + unsigned Size; + LiveIntervalUnion *LIUs; + public: + Array() : Size(0), LIUs(0) {} + ~Array() { clear(); } + + // Initialize the array to have Size entries. + // Reuse an existing allocation if the size matches. + void init(LiveIntervalUnion::Allocator&, unsigned Size); + + unsigned size() const { return Size; } + + void clear(); + + LiveIntervalUnion& operator[](unsigned idx) { + assert(idx < Size && "idx out of bounds"); + return LIUs[idx]; + } + }; +}; + +} // end namespace llvm + +#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION) diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h new file mode 100644 index 0000000..7a3e9e8 --- /dev/null +++ b/include/llvm/CodeGen/LiveRegMatrix.h @@ -0,0 +1,148 @@ +//===-- LiveRegMatrix.h - Track register interference ---------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The LiveRegMatrix analysis pass keeps track of virtual register interference +// along two dimensions: Slot indexes and register units. The matrix is used by +// register allocators to ensure that no interfering virtual registers get +// assigned to overlapping physical registers. +// +// Register units are defined in MCRegisterInfo.h, they represent the smallest +// unit of interference when dealing with overlapping physical registers. The +// LiveRegMatrix is represented as a LiveIntervalUnion per register unit. When +// a virtual register is assigned to a physical register, the live range for +// the virtual register is inserted into the LiveIntervalUnion for each regunit +// in the physreg. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEREGMATRIX_H +#define LLVM_CODEGEN_LIVEREGMATRIX_H + +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/CodeGen/LiveIntervalUnion.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + +class LiveInterval; +class LiveIntervalAnalysis; +class MachineRegisterInfo; +class TargetRegisterInfo; +class VirtRegMap; + +class LiveRegMatrix : public MachineFunctionPass { + const TargetRegisterInfo *TRI; + MachineRegisterInfo *MRI; + LiveIntervals *LIS; + VirtRegMap *VRM; + + // UserTag changes whenever virtual registers have been modified. + unsigned UserTag; + + // The matrix is represented as a LiveIntervalUnion per register unit. + LiveIntervalUnion::Allocator LIUAlloc; + LiveIntervalUnion::Array Matrix; + + // Cached queries per register unit. + OwningArrayPtr<LiveIntervalUnion::Query> Queries; + + // Cached register mask interference info. + unsigned RegMaskTag; + unsigned RegMaskVirtReg; + BitVector RegMaskUsable; + + // MachineFunctionPass boilerplate. + virtual void getAnalysisUsage(AnalysisUsage&) const; + virtual bool runOnMachineFunction(MachineFunction&); + virtual void releaseMemory(); +public: + static char ID; + LiveRegMatrix(); + + //===--------------------------------------------------------------------===// + // High-level interface. + //===--------------------------------------------------------------------===// + // + // Check for interference before assigning virtual registers to physical + // registers. + // + + /// Invalidate cached interference queries after modifying virtual register + /// live ranges. Interference checks may return stale information unless + /// caches are invalidated. + void invalidateVirtRegs() { ++UserTag; } + + enum InterferenceKind { + /// No interference, go ahead and assign. + IK_Free = 0, + + /// Virtual register interference. There are interfering virtual registers + /// assigned to PhysReg or its aliases. This interference could be resolved + /// by unassigning those other virtual registers. + IK_VirtReg, + + /// Register unit interference. A fixed live range is in the way, typically + /// argument registers for a call. This can't be resolved by unassigning + /// other virtual registers. + IK_RegUnit, + + /// RegMask interference. The live range is crossing an instruction with a + /// regmask operand that doesn't preserve PhysReg. This typically means + /// VirtReg is live across a call, and PhysReg isn't call-preserved. + IK_RegMask + }; + + /// Check for interference before assigning VirtReg to PhysReg. + /// If this function returns IK_Free, it is legal to assign(VirtReg, PhysReg). + /// When there is more than one kind of interference, the InterferenceKind + /// with the highest enum value is returned. + InterferenceKind checkInterference(LiveInterval &VirtReg, unsigned PhysReg); + + /// Assign VirtReg to PhysReg. + /// This will mark VirtReg's live range as occupied in the LiveRegMatrix and + /// update VirtRegMap. The live range is expected to be available in PhysReg. + void assign(LiveInterval &VirtReg, unsigned PhysReg); + + /// Unassign VirtReg from its PhysReg. + /// Assuming that VirtReg was previously assigned to a PhysReg, this undoes + /// the assignment and updates VirtRegMap accordingly. + void unassign(LiveInterval &VirtReg); + + //===--------------------------------------------------------------------===// + // Low-level interface. + //===--------------------------------------------------------------------===// + // + // Provide access to the underlying LiveIntervalUnions. + // + + /// Check for regmask interference only. + /// Return true if VirtReg crosses a regmask operand that clobbers PhysReg. + /// If PhysReg is null, check if VirtReg crosses any regmask operands. + bool checkRegMaskInterference(LiveInterval &VirtReg, unsigned PhysReg = 0); + + /// Check for regunit interference only. + /// Return true if VirtReg overlaps a fixed assignment of one of PhysRegs's + /// register units. + bool checkRegUnitInterference(LiveInterval &VirtReg, unsigned PhysReg); + + /// Query a line of the assigned virtual register matrix directly. + /// Use MCRegUnitIterator to enumerate all regunits in the desired PhysReg. + /// This returns a reference to an internal Query data structure that is only + /// valid until the next query() call. + LiveIntervalUnion::Query &query(LiveInterval &VirtReg, unsigned RegUnit); + + /// Directly access the live interval unions per regunit. + /// This returns an array indexed by the regunit number. + LiveIntervalUnion *getLiveUnions() { return &Matrix[0]; } +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_LIVEREGMATRIX_H diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h index 86c4d7c..a3b1855 100644 --- a/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/include/llvm/CodeGen/LiveStackAnalysis.h @@ -16,10 +16,10 @@ #ifndef LLVM_CODEGEN_LIVESTACK_ANALYSIS_H #define LLVM_CODEGEN_LIVESTACK_ANALYSIS_H -#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/LiveInterval.h" -#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Support/Allocator.h" +#include "llvm/Target/TargetRegisterInfo.h" #include <map> namespace llvm { diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index d4bb409..3c5ed92 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -29,16 +29,16 @@ #ifndef LLVM_CODEGEN_LIVEVARIABLES_H #define LLVM_CODEGEN_LIVEVARIABLES_H -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SparseBitVector.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetRegisterInfo.h" namespace llvm { @@ -126,12 +126,6 @@ private: /// building live intervals. SparseBitVector<> PHIJoins; - /// ReservedRegisters - This vector keeps track of which registers - /// are reserved register which are not allocatable by the target machine. - /// We can not track liveness for values that are in this set. - /// - BitVector ReservedRegisters; - private: // Intermediate data structures MachineFunction *MF; diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 77ea4d0..492a3ff 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -14,8 +14,8 @@ #ifndef LLVM_CODEGEN_MACHINEBASICBLOCK_H #define LLVM_CODEGEN_MACHINEBASICBLOCK_H -#include "llvm/CodeGen/MachineInstr.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/Support/DataTypes.h" #include <functional> @@ -146,11 +146,11 @@ public: bundle_iterator(IterTy mii) : MII(mii) {} bundle_iterator(Ty &mi) : MII(mi) { - assert(!mi.isInsideBundle() && + assert(!mi.isBundledWithPred() && "It's not legal to initialize bundle_iterator with a bundled MI"); } bundle_iterator(Ty *mi) : MII(mi) { - assert((!mi || !mi->isInsideBundle()) && + assert((!mi || !mi->isBundledWithPred()) && "It's not legal to initialize bundle_iterator with a bundled MI"); } // Template allows conversion from const to nonconst. @@ -174,13 +174,13 @@ public: // Increment and decrement operators... bundle_iterator &operator--() { // predecrement - Back up do --MII; - while (MII->isInsideBundle()); + while (MII->isBundledWithPred()); return *this; } bundle_iterator &operator++() { // preincrement - Advance - IterTy E = MII->getParent()->instr_end(); - do ++MII; - while (MII != E && MII->isInsideBundle()); + while (MII->isBundledWithSucc()) + ++MII; + ++MII; return *this; } bundle_iterator operator--(int) { // postdecrement operators... @@ -441,80 +441,107 @@ public: void pop_back() { Insts.pop_back(); } void push_back(MachineInstr *MI) { Insts.push_back(MI); } - template<typename IT> - void insert(instr_iterator I, IT S, IT E) { - Insts.insert(I, S, E); - } - instr_iterator insert(instr_iterator I, MachineInstr *M) { - return Insts.insert(I, M); - } - instr_iterator insertAfter(instr_iterator I, MachineInstr *M) { - return Insts.insertAfter(I, M); - } + /// Insert MI into the instruction list before I, possibly inside a bundle. + /// + /// If the insertion point is inside a bundle, MI will be added to the bundle, + /// otherwise MI will not be added to any bundle. That means this function + /// alone can't be used to prepend or append instructions to bundles. See + /// MIBundleBuilder::insert() for a more reliable way of doing that. + instr_iterator insert(instr_iterator I, MachineInstr *M); + /// Insert a range of instructions into the instruction list before I. template<typename IT> void insert(iterator I, IT S, IT E) { Insts.insert(I.getInstrIterator(), S, E); } - iterator insert(iterator I, MachineInstr *M) { - return Insts.insert(I.getInstrIterator(), M); + + /// Insert MI into the instruction list before I. + iterator insert(iterator I, MachineInstr *MI) { + assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && + "Cannot insert instruction with bundle flags"); + return Insts.insert(I.getInstrIterator(), MI); } - iterator insertAfter(iterator I, MachineInstr *M) { - return Insts.insertAfter(I.getInstrIterator(), M); + + /// Insert MI into the instruction list after I. + iterator insertAfter(iterator I, MachineInstr *MI) { + assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && + "Cannot insert instruction with bundle flags"); + return Insts.insertAfter(I.getInstrIterator(), MI); } - /// erase - Remove the specified element or range from the instruction list. - /// These functions delete any instructions removed. + /// Remove an instruction from the instruction list and delete it. /// - instr_iterator erase(instr_iterator I) { - return Insts.erase(I); - } - instr_iterator erase(instr_iterator I, instr_iterator E) { - return Insts.erase(I, E); - } + /// If the instruction is part of a bundle, the other instructions in the + /// bundle will still be bundled after removing the single instruction. + instr_iterator erase(instr_iterator I); + + /// Remove an instruction from the instruction list and delete it. + /// + /// If the instruction is part of a bundle, the other instructions in the + /// bundle will still be bundled after removing the single instruction. instr_iterator erase_instr(MachineInstr *I) { - instr_iterator MII(I); - return erase(MII); + return erase(instr_iterator(I)); } - iterator erase(iterator I); + /// Remove a range of instructions from the instruction list and delete them. iterator erase(iterator I, iterator E) { return Insts.erase(I.getInstrIterator(), E.getInstrIterator()); } + + /// Remove an instruction or bundle from the instruction list and delete it. + /// + /// If I points to a bundle of instructions, they are all erased. + iterator erase(iterator I) { + return erase(I, llvm::next(I)); + } + + /// Remove an instruction from the instruction list and delete it. + /// + /// If I is the head of a bundle of instructions, the whole bundle will be + /// erased. iterator erase(MachineInstr *I) { - iterator MII(I); - return erase(MII); + return erase(iterator(I)); + } + + /// Remove the unbundled instruction from the instruction list without + /// deleting it. + /// + /// This function can not be used to remove bundled instructions, use + /// remove_instr to remove individual instructions from a bundle. + MachineInstr *remove(MachineInstr *I) { + assert(!I->isBundled() && "Cannot remove bundled instructions"); + return Insts.remove(I); } - /// remove - Remove the instruction from the instruction list. This function - /// does not delete the instruction. WARNING: Note, if the specified - /// instruction is a bundle this function will remove all the bundled - /// instructions as well. It is up to the caller to keep a list of the - /// bundled instructions and re-insert them if desired. This function is - /// *not recommended* for manipulating instructions with bundles. Use - /// splice instead. - MachineInstr *remove(MachineInstr *I); + /// Remove the possibly bundled instruction from the instruction list + /// without deleting it. + /// + /// If the instruction is part of a bundle, the other instructions in the + /// bundle will still be bundled after removing the single instruction. + MachineInstr *remove_instr(MachineInstr *I); + void clear() { Insts.clear(); } - /// splice - Take an instruction from MBB 'Other' at the position From, - /// and insert it into this MBB right before 'where'. - void splice(instr_iterator where, MachineBasicBlock *Other, - instr_iterator From) { - Insts.splice(where, Other->Insts, From); + /// Take an instruction from MBB 'Other' at the position From, and insert it + /// into this MBB right before 'Where'. + /// + /// If From points to a bundle of instructions, the whole bundle is moved. + void splice(iterator Where, MachineBasicBlock *Other, iterator From) { + // The range splice() doesn't allow noop moves, but this one does. + if (Where != From) + splice(Where, Other, From, llvm::next(From)); } - void splice(iterator where, MachineBasicBlock *Other, iterator From); - /// splice - Take a block of instructions from MBB 'Other' in the range [From, - /// To), and insert them into this MBB right before 'where'. - void splice(instr_iterator where, MachineBasicBlock *Other, instr_iterator From, - instr_iterator To) { - Insts.splice(where, Other->Insts, From, To); - } - void splice(iterator where, MachineBasicBlock *Other, iterator From, - iterator To) { - Insts.splice(where.getInstrIterator(), Other->Insts, + /// Take a block of instructions from MBB 'Other' in the range [From, To), + /// and insert them into this MBB right before 'Where'. + /// + /// The instruction at 'Where' must not be included in the range of + /// instructions to move. + void splice(iterator Where, MachineBasicBlock *Other, + iterator From, iterator To) { + Insts.splice(Where.getInstrIterator(), Other->Insts, From.getInstrIterator(), To.getInstrIterator()); } @@ -547,6 +574,28 @@ public: return findDebugLoc(MBBI.getInstrIterator()); } + /// Possible outcome of a register liveness query to computeRegisterLiveness() + enum LivenessQueryResult { + LQR_Live, ///< Register is known to be live. + LQR_OverlappingLive, ///< Register itself is not live, but some overlapping + ///< register is. + LQR_Dead, ///< Register is known to be dead. + LQR_Unknown ///< Register liveness not decidable from local + ///< neighborhood. + }; + + /// computeRegisterLiveness - Return whether (physical) register \c Reg + /// has been <def>ined and not <kill>ed as of just before \c MI. + /// + /// Search is localised to a neighborhood of + /// \c Neighborhood instructions before (searching for defs or kills) and + /// Neighborhood instructions after (searching just for defs) MI. + /// + /// \c Reg must be a physical register. + LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, + unsigned Reg, MachineInstr *MI, + unsigned Neighborhood=10); + // Debugging methods. void dump() const; void print(raw_ostream &OS, SlotIndexes* = 0) const; diff --git a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index 12189ce..1c9bdd9 100644 --- a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -15,8 +15,8 @@ #ifndef LLVM_CODEGEN_MACHINEBRANCHPROBABILITYINFO_H #define LLVM_CODEGEN_MACHINEBRANCHPROBABILITYINFO_H -#include "llvm/Pass.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Pass.h" #include "llvm/Support/BranchProbability.h" #include <climits> diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h index 86e8f27..9e41e6e 100644 --- a/include/llvm/CodeGen/MachineCodeEmitter.h +++ b/include/llvm/CodeGen/MachineCodeEmitter.h @@ -19,7 +19,6 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" - #include <string> namespace llvm { diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index d6d65a2..8ed215d 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -25,7 +25,7 @@ namespace llvm { class Constant; class FoldingSetNodeID; -class TargetData; +class DataLayout; class TargetMachine; class Type; class MachineConstantPool; @@ -132,14 +132,14 @@ public: /// address of the function constant pool values. /// @brief The machine constant pool. class MachineConstantPool { - const TargetData *TD; ///< The machine's TargetData. + const DataLayout *TD; ///< The machine's DataLayout. unsigned PoolAlignment; ///< The alignment for the pool. std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants. /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. DenseSet<MachineConstantPoolValue*> MachineCPVsSharingEntries; public: /// @brief The only constructor. - explicit MachineConstantPool(const TargetData *td) + explicit MachineConstantPool(const DataLayout *td) : TD(td), PoolAlignment(1) {} ~MachineConstantPool(); diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 82a4ac8..40b2542 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -15,11 +15,11 @@ #ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H #define LLVM_CODEGEN_MACHINEDOMINATORS_H +#include "llvm/Analysis/DominatorInternals.h" +#include "llvm/Analysis/Dominators.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Analysis/Dominators.h" -#include "llvm/Analysis/DominatorInternals.h" namespace llvm { diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 3c07ceb..93d7728 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -21,7 +21,7 @@ namespace llvm { class raw_ostream; -class TargetData; +class DataLayout; class TargetRegisterClass; class Type; class MachineFunction; @@ -29,6 +29,7 @@ class MachineBasicBlock; class TargetFrameLowering; class BitVector; class Value; +class AllocaInst; /// The CalleeSavedInfo class tracks the information need to locate where a /// callee saved register is in the current frame. @@ -106,14 +107,14 @@ class MachineFrameInfo { /// Alloca - If this stack object is originated from an Alloca instruction /// this value saves the original IR allocation. Can be NULL. - const Value *Alloca; + const AllocaInst *Alloca; // PreAllocated - If true, the object was mapped into the local frame // block and doesn't need additional handling for allocation beyond that. bool PreAllocated; StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, - bool isSS, bool NSP, const Value *Val) + bool isSS, bool NSP, const AllocaInst *Val) : SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM), isSpillSlot(isSS), MayNeedSP(NSP), Alloca(Val), PreAllocated(false) {} }; @@ -220,8 +221,11 @@ class MachineFrameInfo { /// just allocate them normally. bool UseLocalStackAllocationBlock; + /// Whether the "realign-stack" option is on. + bool RealignOption; public: - explicit MachineFrameInfo(const TargetFrameLowering &tfi) : TFI(tfi) { + explicit MachineFrameInfo(const TargetFrameLowering &tfi, bool RealignOpt) + : TFI(tfi), RealignOption(RealignOpt) { StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; @@ -369,7 +373,7 @@ public: /// getObjectAllocation - Return the underlying Alloca of the specified /// stack object if it exists. Returns 0 if none exists. - const Value* getObjectAllocation(int ObjectIdx) const { + const AllocaInst* getObjectAllocation(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); return Objects[ObjectIdx+NumFixedObjects].Alloca; @@ -431,9 +435,7 @@ public: /// ensureMaxAlignment - Make sure the function is at least Align bytes /// aligned. - void ensureMaxAlignment(unsigned Align) { - if (MaxAlignment < Align) MaxAlignment = Align; - } + void ensureMaxAlignment(unsigned Align); /// AdjustsStack - Return true if this function adjusts the stack -- e.g., /// when calling another function. This is only valid during and after @@ -495,26 +497,13 @@ public: /// a nonnegative identifier to represent it. /// int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, - bool MayNeedSP = false, const Value *Alloca = 0) { - assert(Size != 0 && "Cannot allocate zero size stack objects!"); - Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, MayNeedSP, - Alloca)); - int Index = (int)Objects.size() - NumFixedObjects - 1; - assert(Index >= 0 && "Bad frame index!"); - ensureMaxAlignment(Alignment); - return Index; - } + bool MayNeedSP = false, const AllocaInst *Alloca = 0); /// CreateSpillStackObject - Create a new statically sized stack object that /// represents a spill slot, returning a nonnegative identifier to represent /// it. /// - int CreateSpillStackObject(uint64_t Size, unsigned Alignment) { - CreateStackObject(Size, Alignment, true, false); - int Index = (int)Objects.size() - NumFixedObjects - 1; - ensureMaxAlignment(Alignment); - return Index; - } + int CreateSpillStackObject(uint64_t Size, unsigned Alignment); /// RemoveStackObject - Remove or mark dead a statically sized stack object. /// @@ -528,12 +517,7 @@ public: /// variable sized object is created, whether or not the index returned is /// actually used. /// - int CreateVariableSizedObject(unsigned Alignment) { - HasVarSizedObjects = true; - Objects.push_back(StackObject(0, Alignment, 0, false, false, true, 0)); - ensureMaxAlignment(Alignment); - return (int)Objects.size()-NumFixedObjects-1; - } + int CreateVariableSizedObject(unsigned Alignment); /// getCalleeSavedInfo - Returns a reference to call saved info vector for the /// current function. diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 0eb9d0e..cd704c1 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -18,10 +18,11 @@ #ifndef LLVM_CODEGEN_MACHINEFUNCTION_H #define LLVM_CODEGEN_MACHINEFUNCTION_H -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/ilist.h" -#include "llvm/Support/DebugLoc.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/ArrayRecycler.h" +#include "llvm/Support/DebugLoc.h" #include "llvm/Support/Recycler.h" namespace llvm { @@ -105,6 +106,9 @@ class MachineFunction { // Allocation management for instructions in function. Recycler<MachineInstr> InstructionRecycler; + // Allocation management for operand arrays on instructions. + ArrayRecycler<MachineOperand> OperandRecycler; + // Allocation management for basic blocks in function. Recycler<MachineBasicBlock> BasicBlockRecycler; @@ -127,8 +131,8 @@ class MachineFunction { /// about the control flow of such functions. bool ExposesReturnsTwice; - MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT - void operator=(const MachineFunction&); // DO NOT IMPLEMENT + MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; + void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; public: MachineFunction(const Function *Fn, const TargetMachine &TM, unsigned FunctionNum, MachineModuleInfo &MMI, @@ -394,6 +398,21 @@ public: MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, int64_t Offset, uint64_t Size); + typedef ArrayRecycler<MachineOperand>::Capacity OperandCapacity; + + /// Allocate an array of MachineOperands. This is only intended for use by + /// internal MachineInstr functions. + MachineOperand *allocateOperandArray(OperandCapacity Cap) { + return OperandRecycler.allocate(Cap, Allocator); + } + + /// Dellocate an array of MachineOperands and recycle the memory. This is + /// only intended for use by internal MachineInstr functions. + /// Cap must be the same capacity that was used to allocate the array. + void deallocateOperandArray(OperandCapacity Cap, MachineOperand *Array) { + OperandRecycler.deallocate(Cap, Array); + } + /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand /// pointers. This array is owned by the MachineFunction. MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num); diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 4e1533a..89521e8 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -16,17 +16,18 @@ #ifndef LLVM_CODEGEN_MACHINEINSTR_H #define LLVM_CODEGEN_MACHINEINSTR_H -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/Target/TargetOpcodes.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/InlineAsm.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/Support/ArrayRecycler.h" #include "llvm/Support/DebugLoc.h" +#include "llvm/Target/TargetOpcodes.h" #include <vector> namespace llvm { @@ -42,6 +43,10 @@ class MachineMemOperand; //===----------------------------------------------------------------------===// /// MachineInstr - Representation of each machine instruction. /// +/// This class isn't a POD type, but it must have a trivial destructor. When a +/// MachineFunction is deleted, all the contained MachineInstrs are deallocated +/// without having their destructor called. +/// class MachineInstr : public ilist_node<MachineInstr> { public: typedef MachineMemOperand **mmo_iterator; @@ -58,11 +63,18 @@ public: NoFlags = 0, FrameSetup = 1 << 0, // Instruction is used as a part of // function frame setup code. - InsideBundle = 1 << 1 // Instruction is inside a bundle (not - // the first MI in a bundle) + BundledPred = 1 << 1, // Instruction has bundled predecessors. + BundledSucc = 1 << 2 // Instruction has bundled successors. }; private: const MCInstrDesc *MCID; // Instruction descriptor. + MachineBasicBlock *Parent; // Pointer to the owning basic block. + + // Operands are allocated by an ArrayRecycler. + MachineOperand *Operands; // Pointer to the first operand. + unsigned NumOperands; // Number of operands on instruction. + typedef ArrayRecycler<MachineOperand>::Capacity OperandCapacity; + OperandCapacity CapOperands; // Capacity of the Operands array. uint8_t Flags; // Various bits of additional // information about machine @@ -75,15 +87,15 @@ private: // anything other than to convey comment // information to AsmPrinter. - uint16_t NumMemRefs; // information on memory references + uint8_t NumMemRefs; // Information on memory references. mmo_iterator MemRefs; - std::vector<MachineOperand> Operands; // the operands - MachineBasicBlock *Parent; // Pointer to the owning basic block. DebugLoc debugLoc; // Source line information. - MachineInstr(const MachineInstr&); // DO NOT IMPLEMENT - void operator=(const MachineInstr&); // DO NOT IMPLEMENT + MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION; + void operator=(const MachineInstr&) LLVM_DELETED_FUNCTION; + // Use MachineFunction::DeleteMachineInstr() instead. + ~MachineInstr() LLVM_DELETED_FUNCTION; // Intrusive list support friend struct ilist_traits<MachineInstr>; @@ -94,37 +106,11 @@ private: /// MachineInstr in the given MachineFunction. MachineInstr(MachineFunction &, const MachineInstr &); - /// MachineInstr ctor - This constructor creates a dummy MachineInstr with - /// MCID NULL and no operands. - MachineInstr(); - - // The next two constructors have DebugLoc and non-DebugLoc versions; - // over time, the non-DebugLoc versions should be phased out and eventually - // removed. - - /// MachineInstr ctor - This constructor creates a MachineInstr and adds the - /// implicit operands. It reserves space for the number of operands specified - /// by the MCInstrDesc. The version with a DebugLoc should be preferred. - explicit MachineInstr(const MCInstrDesc &MCID, bool NoImp = false); - - /// MachineInstr ctor - Work exactly the same as the ctor above, except that - /// the MachineInstr is created and added to the end of the specified basic - /// block. The version with a DebugLoc should be preferred. - MachineInstr(MachineBasicBlock *MBB, const MCInstrDesc &MCID); - /// MachineInstr ctor - This constructor create a MachineInstr and add the /// implicit operands. It reserves space for number of operands specified by /// MCInstrDesc. An explicit DebugLoc is supplied. - explicit MachineInstr(const MCInstrDesc &MCID, const DebugLoc dl, - bool NoImp = false); - - /// MachineInstr ctor - Work exactly the same as the ctor above, except that - /// the MachineInstr is created and added to the end of the specified basic - /// block. - MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, - const MCInstrDesc &MCID); - - ~MachineInstr(); + MachineInstr(MachineFunction&, const MCInstrDesc &MCID, + const DebugLoc dl, bool NoImp = false); // MachineInstrs are pool-allocated and owned by MachineFunction. friend class MachineFunction; @@ -175,7 +161,9 @@ public: } void setFlags(unsigned flags) { - Flags = flags; + // Filter out the automatically maintained flags. + unsigned Mask = BundledPred | BundledSucc; + Flags = (Flags & Mask) | (flags & ~Mask); } /// clearFlag - Clear a MI flag. @@ -220,21 +208,36 @@ public: /// The first instruction has the special opcode "BUNDLE". It's not "inside" /// a bundle, but the next three MIs are. bool isInsideBundle() const { - return getFlag(InsideBundle); - } - - /// setIsInsideBundle - Set InsideBundle bit. - /// - void setIsInsideBundle(bool Val = true) { - if (Val) - setFlag(InsideBundle); - else - clearFlag(InsideBundle); + return getFlag(BundledPred); } /// isBundled - Return true if this instruction part of a bundle. This is true /// if either itself or its following instruction is marked "InsideBundle". - bool isBundled() const; + bool isBundled() const { + return isBundledWithPred() || isBundledWithSucc(); + } + + /// Return true if this instruction is part of a bundle, and it is not the + /// first instruction in the bundle. + bool isBundledWithPred() const { return getFlag(BundledPred); } + + /// Return true if this instruction is part of a bundle, and it is not the + /// last instruction in the bundle. + bool isBundledWithSucc() const { return getFlag(BundledSucc); } + + /// Bundle this instruction with its predecessor. This can be an unbundled + /// instruction, or it can be the first instruction in a bundle. + void bundleWithPred(); + + /// Bundle this instruction with its successor. This can be an unbundled + /// instruction, or it can be the last instruction in a bundle. + void bundleWithSucc(); + + /// Break bundle above this instruction. + void unbundleFromPred(); + + /// Break bundle below this instruction. + void unbundleFromSucc(); /// getDebugLoc - Returns the debug location id of this MachineInstr. /// @@ -259,7 +262,7 @@ public: /// Access to explicit operands of the instruction. /// - unsigned getNumOperands() const { return (unsigned)Operands.size(); } + unsigned getNumOperands() const { return NumOperands; } const MachineOperand& getOperand(unsigned i) const { assert(i < getNumOperands() && "getOperand() out of range!"); @@ -275,14 +278,14 @@ public: unsigned getNumExplicitOperands() const; /// iterator/begin/end - Iterate over all operands of a machine instruction. - typedef std::vector<MachineOperand>::iterator mop_iterator; - typedef std::vector<MachineOperand>::const_iterator const_mop_iterator; + typedef MachineOperand *mop_iterator; + typedef const MachineOperand *const_mop_iterator; - mop_iterator operands_begin() { return Operands.begin(); } - mop_iterator operands_end() { return Operands.end(); } + mop_iterator operands_begin() { return Operands; } + mop_iterator operands_end() { return Operands + NumOperands; } - const_mop_iterator operands_begin() const { return Operands.begin(); } - const_mop_iterator operands_end() const { return Operands.end(); } + const_mop_iterator operands_begin() const { return Operands; } + const_mop_iterator operands_end() const { return Operands + NumOperands; } /// Access to memory operands of the instruction mmo_iterator memoperands_begin() const { return MemRefs; } @@ -460,6 +463,11 @@ public: /// Instructions with this flag set are not necessarily simple load /// instructions, they may load a value and modify it, for example. bool mayLoad(QueryType Type = AnyInBundle) const { + if (isInlineAsm()) { + unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); + if (ExtraInfo & InlineAsm::Extra_MayLoad) + return true; + } return hasProperty(MCID::MayLoad, Type); } @@ -469,6 +477,11 @@ public: /// instructions, they may store a modified value based on their operands, or /// may not actually modify anything, for example. bool mayStore(QueryType Type = AnyInBundle) const { + if (isInlineAsm()) { + unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); + if (ExtraInfo & InlineAsm::Extra_MayStore) + return true; + } return hasProperty(MCID::MayStore, Type); } @@ -583,14 +596,33 @@ public: bool isIdenticalTo(const MachineInstr *Other, MICheckType Check = CheckDefs) const; - /// removeFromParent - This method unlinks 'this' from the containing basic - /// block, and returns it, but does not delete it. + /// Unlink 'this' from the containing basic block, and return it without + /// deleting it. + /// + /// This function can not be used on bundled instructions, use + /// removeFromBundle() to remove individual instructions from a bundle. MachineInstr *removeFromParent(); - /// eraseFromParent - This method unlinks 'this' from the containing basic - /// block and deletes it. + /// Unlink this instruction from its basic block and return it without + /// deleting it. + /// + /// If the instruction is part of a bundle, the other instructions in the + /// bundle remain bundled. + MachineInstr *removeFromBundle(); + + /// Unlink 'this' from the containing basic block and delete it. + /// + /// If this instruction is the header of a bundle, the whole bundle is erased. + /// This function can not be used for instructions inside a bundle, use + /// eraseFromBundle() to erase individual bundled instructions. void eraseFromParent(); + /// Unlink 'this' form its basic block and delete it. + /// + /// If the instruction is part of a bundle, the other instructions in the + /// bundle remain bundled. + void eraseFromBundle(); + /// isLabel - Returns true if the MachineInstr represents a label. /// bool isLabel() const { @@ -826,13 +858,6 @@ public: /// void clearKillInfo(); - /// copyKillDeadInfo - Copies kill / dead operand properties from MI. - /// - void copyKillDeadInfo(const MachineInstr *MI); - - /// copyPredicates - Copies predicate operand(s) from MI. - void copyPredicates(const MachineInstr *MI); - /// substituteRegister - Replace all occurrences of FromReg with ToReg:SubIdx, /// properly composing subreg indices where necessary. void substituteRegister(unsigned FromReg, unsigned ToReg, unsigned SubIdx, @@ -914,7 +939,7 @@ public: /// copyImplicitOps - Copy implicit register operands from specified /// instruction to this instruction. - void copyImplicitOps(const MachineInstr *MI); + void copyImplicitOps(MachineFunction &MF, const MachineInstr *MI); // // Debugging support @@ -925,10 +950,23 @@ public: //===--------------------------------------------------------------------===// // Accessors used to build up machine instructions. - /// addOperand - Add the specified operand to the instruction. If it is an - /// implicit operand, it is added to the end of the operand list. If it is - /// an explicit operand it is added at the end of the explicit operand list + /// Add the specified operand to the instruction. If it is an implicit + /// operand, it is added to the end of the operand list. If it is an + /// explicit operand it is added at the end of the explicit operand list /// (before the first implicit operand). + /// + /// MF must be the machine function that was used to allocate this + /// instruction. + /// + /// MachineInstrBuilder provides a more convenient interface for creating + /// instructions and adding operands. + void addOperand(MachineFunction &MF, const MachineOperand &Op); + + /// Add an operand without providing an MF reference. This only works for + /// instructions that are inserted in a basic block. + /// + /// MachineInstrBuilder and the two-argument addOperand(MF, MO) should be + /// preferred. void addOperand(const MachineOperand &Op); /// setDesc - Replace the instruction descriptor (thus opcode) of @@ -955,7 +993,8 @@ public: /// list. This does not transfer ownership. void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { MemRefs = NewMemRefs; - NumMemRefs = NewMemRefsEnd - NewMemRefs; + NumMemRefs = uint8_t(NewMemRefsEnd - NewMemRefs); + assert(NumMemRefs == NewMemRefsEnd - NewMemRefs && "Too many memrefs"); } private: @@ -975,7 +1014,7 @@ private: /// addImplicitDefUseOperands - Add all implicit def and use operands to /// this instruction. - void addImplicitDefUseOperands(); + void addImplicitDefUseOperands(MachineFunction &MF); /// RemoveRegOperandsFromUseLists - Unlink all of the register operands in /// this instruction from their respective use lists. This requires that the diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 654361f..a2d3d63 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -42,10 +42,14 @@ namespace RegState { } class MachineInstrBuilder { + MachineFunction *MF; MachineInstr *MI; public: - MachineInstrBuilder() : MI(0) {} - explicit MachineInstrBuilder(MachineInstr *mi) : MI(mi) {} + MachineInstrBuilder() : MF(0), MI(0) {} + + /// Create a MachineInstrBuilder for manipulating an existing instruction. + /// F must be the machine function that was used to allocate I. + MachineInstrBuilder(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {} /// Allow automatic conversion to the machine instruction we are working on. /// @@ -60,86 +64,94 @@ public: unsigned SubReg = 0) const { assert((flags & 0x1) == 0 && "Passing in 'true' to addReg is forbidden! Use enums instead."); - MI->addOperand(MachineOperand::CreateReg(RegNo, - flags & RegState::Define, - flags & RegState::Implicit, - flags & RegState::Kill, - flags & RegState::Dead, - flags & RegState::Undef, - flags & RegState::EarlyClobber, - SubReg, - flags & RegState::Debug, - flags & RegState::InternalRead)); + MI->addOperand(*MF, MachineOperand::CreateReg(RegNo, + flags & RegState::Define, + flags & RegState::Implicit, + flags & RegState::Kill, + flags & RegState::Dead, + flags & RegState::Undef, + flags & RegState::EarlyClobber, + SubReg, + flags & RegState::Debug, + flags & RegState::InternalRead)); return *this; } /// addImm - Add a new immediate operand. /// const MachineInstrBuilder &addImm(int64_t Val) const { - MI->addOperand(MachineOperand::CreateImm(Val)); + MI->addOperand(*MF, MachineOperand::CreateImm(Val)); return *this; } const MachineInstrBuilder &addCImm(const ConstantInt *Val) const { - MI->addOperand(MachineOperand::CreateCImm(Val)); + MI->addOperand(*MF, MachineOperand::CreateCImm(Val)); return *this; } const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { - MI->addOperand(MachineOperand::CreateFPImm(Val)); + MI->addOperand(*MF, MachineOperand::CreateFPImm(Val)); return *this; } const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags = 0) const { - MI->addOperand(MachineOperand::CreateMBB(MBB, TargetFlags)); + MI->addOperand(*MF, MachineOperand::CreateMBB(MBB, TargetFlags)); return *this; } const MachineInstrBuilder &addFrameIndex(int Idx) const { - MI->addOperand(MachineOperand::CreateFI(Idx)); + MI->addOperand(*MF, MachineOperand::CreateFI(Idx)); return *this; } const MachineInstrBuilder &addConstantPoolIndex(unsigned Idx, int Offset = 0, unsigned char TargetFlags = 0) const { - MI->addOperand(MachineOperand::CreateCPI(Idx, Offset, TargetFlags)); + MI->addOperand(*MF, MachineOperand::CreateCPI(Idx, Offset, TargetFlags)); return *this; } const MachineInstrBuilder &addTargetIndex(unsigned Idx, int64_t Offset = 0, unsigned char TargetFlags = 0) const { - MI->addOperand(MachineOperand::CreateTargetIndex(Idx, Offset, TargetFlags)); + MI->addOperand(*MF, MachineOperand::CreateTargetIndex(Idx, Offset, + TargetFlags)); return *this; } const MachineInstrBuilder &addJumpTableIndex(unsigned Idx, unsigned char TargetFlags = 0) const { - MI->addOperand(MachineOperand::CreateJTI(Idx, TargetFlags)); + MI->addOperand(*MF, MachineOperand::CreateJTI(Idx, TargetFlags)); return *this; } const MachineInstrBuilder &addGlobalAddress(const GlobalValue *GV, int64_t Offset = 0, unsigned char TargetFlags = 0) const { - MI->addOperand(MachineOperand::CreateGA(GV, Offset, TargetFlags)); + MI->addOperand(*MF, MachineOperand::CreateGA(GV, Offset, TargetFlags)); return *this; } const MachineInstrBuilder &addExternalSymbol(const char *FnName, unsigned char TargetFlags = 0) const { - MI->addOperand(MachineOperand::CreateES(FnName, TargetFlags)); + MI->addOperand(*MF, MachineOperand::CreateES(FnName, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addBlockAddress(const BlockAddress *BA, + int64_t Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(*MF, MachineOperand::CreateBA(BA, Offset, TargetFlags)); return *this; } const MachineInstrBuilder &addRegMask(const uint32_t *Mask) const { - MI->addOperand(MachineOperand::CreateRegMask(Mask)); + MI->addOperand(*MF, MachineOperand::CreateRegMask(Mask)); return *this; } const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { - MI->addMemOperand(*MI->getParent()->getParent(), MMO); + MI->addMemOperand(*MF, MMO); return *this; } @@ -151,17 +163,17 @@ public: const MachineInstrBuilder &addOperand(const MachineOperand &MO) const { - MI->addOperand(MO); + MI->addOperand(*MF, MO); return *this; } const MachineInstrBuilder &addMetadata(const MDNode *MD) const { - MI->addOperand(MachineOperand::CreateMetadata(MD)); + MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); return *this; } const MachineInstrBuilder &addSym(MCSymbol *Sym) const { - MI->addOperand(MachineOperand::CreateMCSymbol(Sym)); + MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym)); return *this; } @@ -176,17 +188,32 @@ public: } // Add a displacement from an existing MachineOperand with an added offset. - const MachineInstrBuilder &addDisp(const MachineOperand &Disp, - int64_t off) const { + const MachineInstrBuilder &addDisp(const MachineOperand &Disp, int64_t off, + unsigned char TargetFlags = 0) const { switch (Disp.getType()) { default: llvm_unreachable("Unhandled operand type in addDisp()"); case MachineOperand::MO_Immediate: return addImm(Disp.getImm() + off); - case MachineOperand::MO_GlobalAddress: - return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off); + case MachineOperand::MO_GlobalAddress: { + // If caller specifies new TargetFlags then use it, otherwise the + // default behavior is to copy the target flags from the existing + // MachineOperand. This means if the caller wants to clear the + // target flags it needs to do so explicitly. + if (TargetFlags) + return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off, + TargetFlags); + return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off, + Disp.getTargetFlags()); + } } } + + /// Copy all the implicit operands from OtherMI onto this one. + const MachineInstrBuilder ©ImplicitOps(const MachineInstr *OtherMI) { + MI->copyImplicitOps(*MF, OtherMI); + return *this; + } }; /// BuildMI - Builder interface. Specify how to create the initial instruction @@ -195,7 +222,7 @@ public: inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID) { - return MachineInstrBuilder(MF.CreateMachineInstr(MCID, DL)); + return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)); } /// BuildMI - This version of the builder sets up the first operand as a @@ -205,7 +232,7 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID, unsigned DestReg) { - return MachineInstrBuilder(MF.CreateMachineInstr(MCID, DL)) + return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)) .addReg(DestReg, RegState::Define); } @@ -218,9 +245,10 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, DebugLoc DL, const MCInstrDesc &MCID, unsigned DestReg) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL); + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); BB.insert(I, MI); - return MachineInstrBuilder(MI).addReg(DestReg, RegState::Define); + return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define); } inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, @@ -228,9 +256,10 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, DebugLoc DL, const MCInstrDesc &MCID, unsigned DestReg) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL); + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); BB.insert(I, MI); - return MachineInstrBuilder(MI).addReg(DestReg, RegState::Define); + return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define); } inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, @@ -255,18 +284,20 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, DebugLoc DL, const MCInstrDesc &MCID) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL); + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); BB.insert(I, MI); - return MachineInstrBuilder(MI); + return MachineInstrBuilder(MF, MI); } inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::instr_iterator I, DebugLoc DL, const MCInstrDesc &MCID) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL); + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); BB.insert(I, MI); - return MachineInstrBuilder(MI); + return MachineInstrBuilder(MF, MI); } inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, @@ -321,6 +352,98 @@ inline unsigned getUndefRegState(bool B) { inline unsigned getInternalReadRegState(bool B) { return B ? RegState::InternalRead : 0; } +inline unsigned getDebugRegState(bool B) { + return B ? RegState::Debug : 0; +} + + +/// Helper class for constructing bundles of MachineInstrs. +/// +/// MIBundleBuilder can create a bundle from scratch by inserting new +/// MachineInstrs one at a time, or it can create a bundle from a sequence of +/// existing MachineInstrs in a basic block. +class MIBundleBuilder { + MachineBasicBlock &MBB; + MachineBasicBlock::instr_iterator Begin; + MachineBasicBlock::instr_iterator End; + +public: + /// Create an MIBundleBuilder that inserts instructions into a new bundle in + /// BB above the bundle or instruction at Pos. + MIBundleBuilder(MachineBasicBlock &BB, + MachineBasicBlock::iterator Pos) + : MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {} + + /// Create a bundle from the sequence of instructions between B and E. + MIBundleBuilder(MachineBasicBlock &BB, + MachineBasicBlock::iterator B, + MachineBasicBlock::iterator E) + : MBB(BB), Begin(B.getInstrIterator()), End(E.getInstrIterator()) { + assert(B != E && "No instructions to bundle"); + ++B; + while (B != E) { + MachineInstr *MI = B; + ++B; + MI->bundleWithPred(); + } + } + + /// Create an MIBundleBuilder representing an existing instruction or bundle + /// that has MI as its head. + explicit MIBundleBuilder(MachineInstr *MI) + : MBB(*MI->getParent()), Begin(MI) { + MachineBasicBlock::iterator I = MI; + ++I; + End = I.getInstrIterator(); + } + + /// Return a reference to the basic block containing this bundle. + MachineBasicBlock &getMBB() const { return MBB; } + + /// Return true if no instructions have been inserted in this bundle yet. + /// Empty bundles aren't representable in a MachineBasicBlock. + bool empty() const { return Begin == End; } + + /// Return an iterator to the first bundled instruction. + MachineBasicBlock::instr_iterator begin() const { return Begin; } + + /// Return an iterator beyond the last bundled instruction. + MachineBasicBlock::instr_iterator end() const { return End; } + + /// Insert MI into this bundle before I which must point to an instruction in + /// the bundle, or end(). + MIBundleBuilder &insert(MachineBasicBlock::instr_iterator I, + MachineInstr *MI) { + MBB.insert(I, MI); + if (I == Begin) { + if (!empty()) + MI->bundleWithSucc(); + Begin = MI; + return *this; + } + if (I == End) { + MI->bundleWithPred(); + return *this; + } + // MI was inserted in the middle of the bundle, so its neighbors' flags are + // already fine. Update MI's bundle flags manually. + MI->setFlag(MachineInstr::BundledPred); + MI->setFlag(MachineInstr::BundledSucc); + return *this; + } + + /// Insert MI into MBB by prepending it to the instructions in the bundle. + /// MI will become the first instruction in the bundle. + MIBundleBuilder &prepend(MachineInstr *MI) { + return insert(begin(), MI); + } + + /// Insert MI into MBB by appending it to the instructions in the bundle. + /// MI will become the last instruction in the bundle. + MIBundleBuilder &append(MachineInstr *MI) { + return insert(end(), MI); + } +}; } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h index dc5f9a6..3c60ad1 100644 --- a/include/llvm/CodeGen/MachineInstrBundle.h +++ b/include/llvm/CodeGen/MachineInstrBundle.h @@ -130,9 +130,9 @@ public: return OpI - InstrI->operands_begin(); } - /// RegInfo - Information about a virtual register used by a set of operands. + /// VirtRegInfo - Information about a virtual register used by a set of operands. /// - struct RegInfo { + struct VirtRegInfo { /// Reads - One of the operands read the virtual register. This does not /// include <undef> or <internal> use operands, see MO::readsReg(). bool Reads; @@ -146,6 +146,29 @@ public: bool Tied; }; + /// PhysRegInfo - Information about a physical register used by a set of + /// operands. + struct PhysRegInfo { + /// Clobbers - Reg or an overlapping register is defined, or a regmask + /// clobbers Reg. + bool Clobbers; + + /// Defines - Reg or a super-register is defined. + bool Defines; + + /// Reads - Read or a super-register is read. + bool Reads; + + /// ReadsOverlap - Reg or an overlapping register is read. + bool ReadsOverlap; + + /// DefinesDead - All defs of a Reg or a super-register are dead. + bool DefinesDead; + + /// There is a kill of Reg or a super-register. + bool Kills; + }; + /// analyzeVirtReg - Analyze how the current instruction or bundle uses a /// virtual register. This function should not be called after operator++(), /// it expects a fresh iterator. @@ -154,8 +177,16 @@ public: /// @param Ops When set, this vector will receive an (MI, OpNum) entry for /// each operand referring to Reg. /// @returns A filled-in RegInfo struct. - RegInfo analyzeVirtReg(unsigned Reg, + VirtRegInfo analyzeVirtReg(unsigned Reg, SmallVectorImpl<std::pair<MachineInstr*, unsigned> > *Ops = 0); + + /// analyzePhysReg - Analyze how the current instruction or bundle uses a + /// physical register. This function should not be called after operator++(), + /// it expects a fresh iterator. + /// + /// @param Reg The physical register to analyze. + /// @returns A filled-in PhysRegInfo struct. + PhysRegInfo analyzePhysReg(unsigned Reg, const TargetRegisterInfo *TRI); }; /// MIOperands - Iterate over operands of a single instruction. diff --git a/include/llvm/CodeGen/MachineJumpTableInfo.h b/include/llvm/CodeGen/MachineJumpTableInfo.h index f7c4e86..adcd1d0 100644 --- a/include/llvm/CodeGen/MachineJumpTableInfo.h +++ b/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -20,13 +20,13 @@ #ifndef LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H #define LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H -#include <vector> #include <cassert> +#include <vector> namespace llvm { class MachineBasicBlock; -class TargetData; +class DataLayout; class raw_ostream; /// MachineJumpTableEntry - One jump table in the jump table info. @@ -84,9 +84,9 @@ public: JTEntryKind getEntryKind() const { return EntryKind; } /// getEntrySize - Return the size of each entry in the jump table. - unsigned getEntrySize(const TargetData &TD) const; + unsigned getEntrySize(const DataLayout &TD) const; /// getEntryAlignment - Return the alignment of each entry in the jump table. - unsigned getEntryAlignment(const TargetData &TD) const; + unsigned getEntryAlignment(const DataLayout &TD) const; /// createJumpTableIndex - Create a new jump table. /// diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 3e204be..99da6b2 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -30,8 +30,8 @@ #ifndef LLVM_CODEGEN_MACHINE_LOOP_INFO_H #define LLVM_CODEGEN_MACHINE_LOOP_INFO_H -#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" namespace llvm { @@ -73,8 +73,8 @@ class MachineLoopInfo : public MachineFunctionPass { LoopInfoBase<MachineBasicBlock, MachineLoop> LI; friend class LoopBase<MachineBasicBlock, MachineLoop>; - void operator=(const MachineLoopInfo &); // do not implement - MachineLoopInfo(const MachineLoopInfo &); // do not implement + void operator=(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; + MachineLoopInfo(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; public: static char ID; // Pass identification, replacement for typeid diff --git a/include/llvm/CodeGen/MachineLoopRanges.h b/include/llvm/CodeGen/MachineLoopRanges.h deleted file mode 100644 index 6a30e8b..0000000 --- a/include/llvm/CodeGen/MachineLoopRanges.h +++ /dev/null @@ -1,112 +0,0 @@ -//===- MachineLoopRanges.h - Ranges of machine loops -----------*- c++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides the interface to the MachineLoopRanges analysis. -// -// Provide on-demand information about the ranges of machine instructions -// covered by a loop. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINELOOPRANGES_H -#define LLVM_CODEGEN_MACHINELOOPRANGES_H - -#include "llvm/ADT/IntervalMap.h" -#include "llvm/CodeGen/SlotIndexes.h" - -namespace llvm { - -class MachineLoop; -class MachineLoopInfo; -class raw_ostream; - -/// MachineLoopRange - Range information for a single loop. -class MachineLoopRange { - friend class MachineLoopRanges; - -public: - typedef IntervalMap<SlotIndex, unsigned, 4> Map; - typedef Map::Allocator Allocator; - -private: - /// The mapped loop. - const MachineLoop *const Loop; - - /// Map intervals to a bit mask. - /// Bit 0 = inside loop block. - Map Intervals; - - /// Loop area as measured by SlotIndex::distance. - unsigned Area; - - /// Create a MachineLoopRange, only accessible to MachineLoopRanges. - MachineLoopRange(const MachineLoop*, Allocator&, SlotIndexes&); - -public: - /// getLoop - Return the mapped machine loop. - const MachineLoop *getLoop() const { return Loop; } - - /// overlaps - Return true if this loop overlaps the given range of machine - /// inteructions. - bool overlaps(SlotIndex Start, SlotIndex Stop); - - /// getNumber - Return the loop number. This is the same as the number of the - /// header block. - unsigned getNumber() const; - - /// getArea - Return the loop area. This number is approximately proportional - /// to the number of instructions in the loop. - unsigned getArea() const { return Area; } - - /// getMap - Allow public read-only access for IntervalMapOverlaps. - const Map &getMap() { return Intervals; } - - /// print - Print loop ranges on OS. - void print(raw_ostream&) const; - - /// byNumber - Comparator for array_pod_sort that sorts a list of - /// MachineLoopRange pointers by number. - static int byNumber(const void*, const void*); - - /// byAreaDesc - Comparator for array_pod_sort that sorts a list of - /// MachineLoopRange pointers by descending area, then by number. - static int byAreaDesc(const void*, const void*); -}; - -raw_ostream &operator<<(raw_ostream&, const MachineLoopRange&); - -/// MachineLoopRanges - Analysis pass that provides on-demand per-loop range -/// information. -class MachineLoopRanges : public MachineFunctionPass { - typedef DenseMap<const MachineLoop*, MachineLoopRange*> CacheMap; - typedef MachineLoopRange::Allocator MapAllocator; - - MapAllocator Allocator; - SlotIndexes *Indexes; - CacheMap Cache; - -public: - static char ID; // Pass identification, replacement for typeid - - MachineLoopRanges() : MachineFunctionPass(ID), Indexes(0) {} - ~MachineLoopRanges() { releaseMemory(); } - - /// getLoopRange - Return the range of loop. - MachineLoopRange *getLoopRange(const MachineLoop *Loop); - -private: - virtual bool runOnMachineFunction(MachineFunction&); - virtual void releaseMemory(); - virtual void getAnalysisUsage(AnalysisUsage&) const; -}; - - -} // end namespace llvm - -#endif // LLVM_CODEGEN_MACHINELOOPRANGES_H diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 6b88d4a..6194d05 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -31,19 +31,19 @@ #ifndef LLVM_CODEGEN_MACHINEMODULEINFO_H #define LLVM_CODEGEN_MACHINEMODULEINFO_H -#include "llvm/Pass.h" -#include "llvm/GlobalValue.h" -#include "llvm/Metadata.h" -#include "llvm/MC/MachineLocation.h" -#include "llvm/MC/MCContext.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/DebugLoc.h" -#include "llvm/Support/ValueHandle.h" -#include "llvm/Support/DataTypes.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Metadata.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/Pass.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ValueHandle.h" namespace llvm { @@ -180,8 +180,9 @@ public: const MCObjectFileInfo *MOFI); ~MachineModuleInfo(); - bool doInitialization(); - bool doFinalization(); + // Initialization and Finalization + virtual bool doInitialization(Module &); + virtual bool doFinalization(Module &); /// EndFunction - Discard function meta information. /// @@ -372,7 +373,7 @@ public: /// getCurrentCallSite - Get the call site currently being processed, if any. /// return zero if none. - unsigned getCurrentCallSite(void) { return CurCallSite; } + unsigned getCurrentCallSite() { return CurCallSite; } /// getTypeInfos - Return a reference to the C++ typeinfo for the current /// function. diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h index 9401ffd..7afc7eb 100644 --- a/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -38,7 +38,7 @@ namespace llvm { /// this GV is external. DenseMap<MCSymbol*, StubValueTy> HiddenGVStubs; - virtual void Anchor(); // Out of line virtual method. + virtual void anchor(); // Out of line virtual method. public: MachineModuleInfoMachO(const MachineModuleInfo &) {} @@ -76,7 +76,7 @@ namespace llvm { /// mode. DenseMap<MCSymbol*, StubValueTy> GVStubs; - virtual void Anchor(); // Out of line virtual method. + virtual void anchor(); // Out of line virtual method. public: MachineModuleInfoELF(const MachineModuleInfo &) {} diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 0b9d67f..414770b 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -35,6 +35,11 @@ class MCSymbol; /// MachineOperand class - Representation of each machine instruction operand. /// +/// This class isn't a POD type because it has a private constructor, but its +/// destructor must be trivial. Functions like MachineInstr::addOperand(), +/// MachineRegisterInfo::moveOperands(), and MF::DeleteMachineInstr() depend on +/// not having to call the MachineOperand destructor. +/// class MachineOperand { public: enum MachineOperandType { @@ -60,15 +65,11 @@ private: /// union. unsigned char OpKind; // MachineOperandType - // This union is discriminated by OpKind. - union { - /// SubReg - Subregister number, only valid for MO_Register. A value of 0 - /// indicates the MO_Register has no subReg. - unsigned char SubReg; - - /// TargetFlags - This is a set of target-specific operand flags. - unsigned char TargetFlags; - }; + /// Subregister number for MO_Register. A value of 0 indicates the + /// MO_Register has no subReg. + /// + /// For all other kinds of operands, this field holds target-specific flags. + unsigned SubReg_TargetFlags : 12; /// TiedTo - Non-zero when this register operand is tied to another register /// operand. The encoding of this field is described in the block comment @@ -176,24 +177,25 @@ private: } OffsetedInfo; } Contents; - explicit MachineOperand(MachineOperandType K) : OpKind(K), ParentMI(0) { - TargetFlags = 0; - } + explicit MachineOperand(MachineOperandType K) + : OpKind(K), SubReg_TargetFlags(0), ParentMI(0) {} public: /// getType - Returns the MachineOperandType for this operand. /// MachineOperandType getType() const { return (MachineOperandType)OpKind; } - unsigned char getTargetFlags() const { - return isReg() ? 0 : TargetFlags; + unsigned getTargetFlags() const { + return isReg() ? 0 : SubReg_TargetFlags; } - void setTargetFlags(unsigned char F) { + void setTargetFlags(unsigned F) { assert(!isReg() && "Register operands can't have target flags"); - TargetFlags = F; + SubReg_TargetFlags = F; + assert(SubReg_TargetFlags == F && "Target flags out of range"); } - void addTargetFlag(unsigned char F) { + void addTargetFlag(unsigned F) { assert(!isReg() && "Register operands can't have target flags"); - TargetFlags |= F; + SubReg_TargetFlags |= F; + assert((SubReg_TargetFlags & F) && "Target flags out of range"); } @@ -261,7 +263,7 @@ public: unsigned getSubReg() const { assert(isReg() && "Wrong MachineOperand accessor"); - return (unsigned)SubReg; + return SubReg_TargetFlags; } bool isUse() const { @@ -336,7 +338,8 @@ public: void setSubReg(unsigned subReg) { assert(isReg() && "Wrong MachineOperand accessor"); - SubReg = (unsigned char)subReg; + SubReg_TargetFlags = subReg; + assert(SubReg_TargetFlags == subReg && "SubReg out of range"); } /// substVirtReg - Substitute the current register with the virtual @@ -574,7 +577,7 @@ public: Op.SmallContents.RegNo = Reg; Op.Contents.Reg.Prev = 0; Op.Contents.Reg.Next = 0; - Op.SubReg = SubReg; + Op.setSubReg(SubReg); return Op; } static MachineOperand CreateMBB(MachineBasicBlock *MBB, @@ -628,11 +631,11 @@ public: Op.setTargetFlags(TargetFlags); return Op; } - static MachineOperand CreateBA(const BlockAddress *BA, + static MachineOperand CreateBA(const BlockAddress *BA, int64_t Offset, unsigned char TargetFlags = 0) { MachineOperand Op(MachineOperand::MO_BlockAddress); Op.Contents.OffsetedInfo.Val.BA = BA; - Op.setOffset(0); // Offset is always 0. + Op.setOffset(Offset); Op.setTargetFlags(TargetFlags); return Op; } @@ -687,6 +690,9 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand& MO) { return OS; } + // See friend declaration above. This additional declaration is required in + // order to compile LLVM with IBM xlC compiler. + hash_code hash_value(const MachineOperand &MO); } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h new file mode 100644 index 0000000..00a60cb --- /dev/null +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -0,0 +1,87 @@ +//=- llvm/CodeGen/MachineDominators.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 exposes interfaces to post dominance information for +// target-specific code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEPOSTDOMINATORS_H +#define LLVM_CODEGEN_MACHINEPOSTDOMINATORS_H + +#include "llvm/Analysis/DominatorInternals.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + +/// +/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used +/// to compute the a post-dominator tree. +/// +struct MachinePostDominatorTree : public MachineFunctionPass { +private: + DominatorTreeBase<MachineBasicBlock> *DT; + +public: + static char ID; + + MachinePostDominatorTree(); + + ~MachinePostDominatorTree(); + + FunctionPass *createMachinePostDominatorTreePass(); + + const std::vector<MachineBasicBlock *> &getRoots() const { + return DT->getRoots(); + } + + MachineDomTreeNode *getRootNode() const { + return DT->getRootNode(); + } + + MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { + return DT->getNode(BB); + } + + MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { + return DT->getNode(BB); + } + + bool dominates(MachineDomTreeNode *A, MachineDomTreeNode *B) const { + return DT->dominates(A, B); + } + + bool dominates(MachineBasicBlock *A, MachineBasicBlock *B) const { + return DT->dominates(A, B); + } + + bool + properlyDominates(const MachineDomTreeNode *A, MachineDomTreeNode *B) const { + return DT->properlyDominates(A, B); + } + + bool + properlyDominates(MachineBasicBlock *A, MachineBasicBlock *B) const { + return DT->properlyDominates(A, B); + } + + MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A, + MachineBasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void print(llvm::raw_ostream &OS, const Module *M = 0) const; +}; +} //end of namespace llvm + +#endif diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 42a8aa4..36427e9 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -14,10 +14,10 @@ #ifndef LLVM_CODEGEN_MACHINEREGISTERINFO_H #define LLVM_CODEGEN_MACHINEREGISTERINFO_H -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" +#include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Target/TargetRegisterInfo.h" #include <vector> namespace llvm { @@ -77,16 +77,20 @@ class MachineRegisterInfo { return MO->Contents.Reg.Next; } - /// UsedPhysRegs - This is a bit vector that is computed and set by the + /// UsedRegUnits - This is a bit vector that is computed and set by the /// register allocator, and must be kept up to date by passes that run after /// register allocation (though most don't modify this). This is used /// so that the code generator knows which callee save registers to save and /// for other target specific uses. - /// This vector only has bits set for registers explicitly used, not their - /// aliases. - BitVector UsedPhysRegs; - - /// UsedPhysRegMask - Additional used physregs, but including aliases. + /// This vector has bits set for register units that are modified in the + /// current function. It doesn't include registers clobbered by function + /// calls with register mask operands. + BitVector UsedRegUnits; + + /// UsedPhysRegMask - Additional used physregs including aliases. + /// This bit vector represents all the registers clobbered by function calls. + /// It can model things that UsedRegUnits can't, such as function calls that + /// clobber ymm7 but preserve the low half in xmm7. BitVector UsedPhysRegMask; /// ReservedRegs - This is a bit vector of reserved registers. The target @@ -95,9 +99,6 @@ class MachineRegisterInfo { /// started. BitVector ReservedRegs; - /// AllocatableRegs - From TRI->getAllocatableSet. - mutable BitVector AllocatableRegs; - /// LiveIns/LiveOuts - Keep track of the physical registers that are /// livein/liveout of the function. Live in values are typically arguments in /// registers, live out values are typically return values in registers. @@ -106,8 +107,8 @@ class MachineRegisterInfo { std::vector<std::pair<unsigned, unsigned> > LiveIns; std::vector<unsigned> LiveOuts; - MachineRegisterInfo(const MachineRegisterInfo&); // DO NOT IMPLEMENT - void operator=(const MachineRegisterInfo&); // DO NOT IMPLEMENT + MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; + void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; public: explicit MachineRegisterInfo(const TargetRegisterInfo &TRI); ~MachineRegisterInfo(); @@ -155,6 +156,9 @@ public: // Strictly for use by MachineInstr.cpp. void removeRegOperandFromUseList(MachineOperand *MO); + // Strictly for use by MachineInstr.cpp. + void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps); + /// reg_begin/reg_end - Provide iteration support to walk over all definitions /// and uses of a register within the MachineFunction that corresponds to this /// MachineRegisterInfo object. @@ -360,29 +364,27 @@ public: //===--------------------------------------------------------------------===// /// isPhysRegUsed - Return true if the specified register is used in this - /// function. This only works after register allocation. + /// function. Also check for clobbered aliases and registers clobbered by + /// function calls with register mask operands. + /// + /// This only works after register allocation. It is primarily used by + /// PrologEpilogInserter to determine which callee-saved registers need + /// spilling. bool isPhysRegUsed(unsigned Reg) const { - return UsedPhysRegs.test(Reg) || UsedPhysRegMask.test(Reg); - } - - /// isPhysRegOrOverlapUsed - Return true if Reg or any overlapping register - /// is used in this function. - bool isPhysRegOrOverlapUsed(unsigned Reg) const { if (UsedPhysRegMask.test(Reg)) return true; - for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) - if (UsedPhysRegs.test(*AI)) + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + if (UsedRegUnits.test(*Units)) return true; return false; } /// setPhysRegUsed - Mark the specified register used in this function. /// This should only be called during and after register allocation. - void setPhysRegUsed(unsigned Reg) { UsedPhysRegs.set(Reg); } - - /// addPhysRegsUsed - Mark the specified registers used in this function. - /// This should only be called during and after register allocation. - void addPhysRegsUsed(const BitVector &Regs) { UsedPhysRegs |= Regs; } + void setPhysRegUsed(unsigned Reg) { + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + UsedRegUnits.set(*Units); + } /// addPhysRegsUsedFromRegMask - Mark any registers not in RegMask as used. /// This corresponds to the bit mask attached to register mask operands. @@ -393,8 +395,9 @@ public: /// setPhysRegUnused - Mark the specified register unused in this function. /// This should only be called during and after register allocation. void setPhysRegUnused(unsigned Reg) { - UsedPhysRegs.reset(Reg); UsedPhysRegMask.reset(Reg); + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + UsedRegUnits.reset(*Units); } @@ -427,6 +430,34 @@ public: return !reservedRegsFrozen() || ReservedRegs.test(PhysReg); } + /// getReservedRegs - Returns a reference to the frozen set of reserved + /// registers. This method should always be preferred to calling + /// TRI::getReservedRegs() when possible. + const BitVector &getReservedRegs() const { + assert(reservedRegsFrozen() && + "Reserved registers haven't been frozen yet. " + "Use TRI::getReservedRegs()."); + return ReservedRegs; + } + + /// isReserved - Returns true when PhysReg is a reserved register. + /// + /// Reserved registers may belong to an allocatable register class, but the + /// target has explicitly requested that they are not used. + /// + bool isReserved(unsigned PhysReg) const { + return getReservedRegs().test(PhysReg); + } + + /// isAllocatable - Returns true when PhysReg belongs to an allocatable + /// register class and it hasn't been reserved. + /// + /// Allocatable registers may show up in the allocation order of some virtual + /// register, so a register allocator needs to track its liveness and + /// availability. + bool isAllocatable(unsigned PhysReg) const { + return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg); + } //===--------------------------------------------------------------------===// // LiveIn/LiveOut Management diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index cbb45a7..edf93d1 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -14,6 +14,8 @@ #ifndef LLVM_CODEGEN_MACHINESSAUPDATER_H #define LLVM_CODEGEN_MACHINESSAUPDATER_H +#include "llvm/Support/Compiler.h" + namespace llvm { class MachineBasicBlock; class MachineFunction; @@ -106,8 +108,8 @@ private: void ReplaceRegWith(unsigned OldReg, unsigned NewReg); unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB); - void operator=(const MachineSSAUpdater&); // DO NOT IMPLEMENT - MachineSSAUpdater(const MachineSSAUpdater&); // DO NOT IMPLEMENT + void operator=(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; + MachineSSAUpdater(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 8da2045..88f347e 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -28,9 +28,15 @@ #define MACHINESCHEDULER_H #include "llvm/CodeGen/MachinePassRegistry.h" +#include "llvm/CodeGen/RegisterPressure.h" +#include "llvm/CodeGen/ScheduleDAGInstrs.h" +#include "llvm/Target/TargetInstrInfo.h" namespace llvm { +extern cl::opt<bool> ForceTopDown; +extern cl::opt<bool> ForceBottomUp; + class AliasAnalysis; class LiveIntervals; class MachineDominatorTree; @@ -93,6 +99,260 @@ public: } }; +class ScheduleDAGMI; + +/// MachineSchedStrategy - Interface to the scheduling algorithm used by +/// ScheduleDAGMI. +class MachineSchedStrategy { +public: + virtual ~MachineSchedStrategy() {} + + /// Initialize the strategy after building the DAG for a new region. + virtual void initialize(ScheduleDAGMI *DAG) = 0; + + /// Notify this strategy that all roots have been released (including those + /// that depend on EntrySU or ExitSU). + virtual void registerRoots() {} + + /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to + /// schedule the node at the top of the unscheduled region. Otherwise it will + /// be scheduled at the bottom. + virtual SUnit *pickNode(bool &IsTopNode) = 0; + + /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an + /// instruction and updated scheduled/remaining flags in the DAG nodes. + virtual void schedNode(SUnit *SU, bool IsTopNode) = 0; + + /// When all predecessor dependencies have been resolved, free this node for + /// top-down scheduling. + virtual void releaseTopNode(SUnit *SU) = 0; + /// When all successor dependencies have been resolved, free this node for + /// bottom-up scheduling. + virtual void releaseBottomNode(SUnit *SU) = 0; +}; + +/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience +/// methods for pushing and removing nodes. ReadyQueue's are uniquely identified +/// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in. +/// +/// This is a convenience class that may be used by implementations of +/// MachineSchedStrategy. +class ReadyQueue { + unsigned ID; + std::string Name; + std::vector<SUnit*> Queue; + +public: + ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {} + + unsigned getID() const { return ID; } + + StringRef getName() const { return Name; } + + // SU is in this queue if it's NodeQueueID is a superset of this ID. + bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); } + + bool empty() const { return Queue.empty(); } + + void clear() { Queue.clear(); } + + unsigned size() const { return Queue.size(); } + + typedef std::vector<SUnit*>::iterator iterator; + + iterator begin() { return Queue.begin(); } + + iterator end() { return Queue.end(); } + + iterator find(SUnit *SU) { + return std::find(Queue.begin(), Queue.end(), SU); + } + + void push(SUnit *SU) { + Queue.push_back(SU); + SU->NodeQueueId |= ID; + } + + iterator remove(iterator I) { + (*I)->NodeQueueId &= ~ID; + *I = Queue.back(); + unsigned idx = I - Queue.begin(); + Queue.pop_back(); + return Queue.begin() + idx; + } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + void dump(); +#endif +}; + +/// Mutate the DAG as a postpass after normal DAG building. +class ScheduleDAGMutation { +public: + virtual ~ScheduleDAGMutation() {} + + virtual void apply(ScheduleDAGMI *DAG) = 0; +}; + +/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that schedules +/// machine instructions while updating LiveIntervals and tracking regpressure. +class ScheduleDAGMI : public ScheduleDAGInstrs { +protected: + AliasAnalysis *AA; + RegisterClassInfo *RegClassInfo; + MachineSchedStrategy *SchedImpl; + + /// Topo - A topological ordering for SUnits which permits fast IsReachable + /// and similar queries. + ScheduleDAGTopologicalSort Topo; + + /// Ordered list of DAG postprocessing steps. + std::vector<ScheduleDAGMutation*> Mutations; + + MachineBasicBlock::iterator LiveRegionEnd; + + /// Register pressure in this region computed by buildSchedGraph. + 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; + + /// The top of the unscheduled zone. + MachineBasicBlock::iterator CurrentTop; + IntervalPressure TopPressure; + RegPressureTracker TopRPTracker; + + /// The bottom of the unscheduled zone. + MachineBasicBlock::iterator CurrentBottom; + IntervalPressure BotPressure; + RegPressureTracker BotRPTracker; + + /// Record the next node in a scheduled cluster. + const SUnit *NextClusterPred; + const SUnit *NextClusterSucc; + +#ifndef NDEBUG + /// The number of instructions scheduled so far. Used to cut off the + /// scheduler at the point determined by misched-cutoff. + unsigned NumInstrsScheduled; +#endif + +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), + Topo(SUnits, &ExitSU), RPTracker(RegPressure), CurrentTop(), + TopRPTracker(TopPressure), CurrentBottom(), BotRPTracker(BotPressure), + NextClusterPred(NULL), NextClusterSucc(NULL) { +#ifndef NDEBUG + NumInstrsScheduled = 0; +#endif + } + + virtual ~ScheduleDAGMI() { + DeleteContainerPointers(Mutations); + delete SchedImpl; + } + + /// 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. + /// + /// ScheduleDAGMI takes ownership of the Mutation object. + void addMutation(ScheduleDAGMutation *Mutation) { + Mutations.push_back(Mutation); + } + + /// \brief Add a DAG edge to the given SU with the given predecessor + /// dependence data. + /// + /// \returns true if the edge may be added without creating a cycle OR if an + /// equivalent edge already existed (false indicates failure). + bool addEdge(SUnit *SuccSU, const SDep &PredDep); + + MachineBasicBlock::iterator top() const { return CurrentTop; } + MachineBasicBlock::iterator bottom() const { return CurrentBottom; } + + /// Implement the ScheduleDAGInstrs interface for handling the next scheduling + /// region. This covers all instructions in a block, while schedule() may only + /// cover a subset. + void enterRegion(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned endcount); + + + /// Implement ScheduleDAGInstrs interface for scheduling a sequence of + /// reorderable instructions. + virtual void schedule(); + + /// Get current register pressure for the top scheduled instructions. + const IntervalPressure &getTopPressure() const { return TopPressure; } + const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; } + + /// Get current register pressure for the bottom scheduled instructions. + const IntervalPressure &getBotPressure() const { return BotPressure; } + const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; } + + /// Get register pressure for the entire scheduling region before scheduling. + const IntervalPressure &getRegPressure() const { return RegPressure; } + + const std::vector<PressureElement> &getRegionCriticalPSets() const { + return RegionCriticalPSets; + } + + const SUnit *getNextClusterPred() const { return NextClusterPred; } + + const SUnit *getNextClusterSucc() const { return NextClusterSucc; } + +protected: + // Top-Level entry points for the schedule() driver... + + /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking + /// enabled. This sets up three trackers. RPTracker will cover the entire DAG + /// region, TopTracker and BottomTracker will be initialized to the top and + /// bottom of the DAG region without covereing any unscheduled instruction. + void buildDAGWithRegPressure(); + + /// Apply each ScheduleDAGMutation step in order. This allows different + /// instances of ScheduleDAGMI to perform custom DAG postprocessing. + void postprocessDAG(); + + /// Identify DAG roots and setup scheduler queues. + void initQueues(); + + /// Move an instruction and update register pressure. + void scheduleMI(SUnit *SU, bool IsTopNode); + + /// Update scheduler DAG and queues after scheduling an instruction. + void updateQueues(SUnit *SU, bool IsTopNode); + + /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues. + void placeDebugValues(); + + /// \brief dump the scheduled Sequence. + void dumpSchedule() const; + + // Lesser helpers... + + void initRegPressure(); + + void updateScheduledPressure(std::vector<unsigned> NewMaxPressure); + + void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); + bool checkSchedLimit(); + + void releaseRoots(); + + void releaseSucc(SUnit *SU, SDep *SuccEdge); + void releaseSuccessors(SUnit *SU); + void releasePred(SUnit *SU, SDep *PredEdge); + void releasePredecessors(SUnit *SU); +}; + } // namespace llvm #endif diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index a5d8b0d..85bf511 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -16,7 +16,8 @@ #define LLVM_CODEGEN_PBQP_GRAPH_H #include "Math.h" - +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" #include <list> #include <map> @@ -31,16 +32,16 @@ namespace PBQP { class NodeEntry; class EdgeEntry; - typedef std::list<NodeEntry> NodeList; - typedef std::list<EdgeEntry> EdgeList; + typedef llvm::ilist<NodeEntry> NodeList; + typedef llvm::ilist<EdgeEntry> EdgeList; public: - typedef NodeList::iterator NodeItr; - typedef NodeList::const_iterator ConstNodeItr; + typedef NodeEntry* NodeItr; + typedef const NodeEntry* ConstNodeItr; - typedef EdgeList::iterator EdgeItr; - typedef EdgeList::const_iterator ConstEdgeItr; + typedef EdgeEntry* EdgeItr; + typedef const EdgeEntry* ConstEdgeItr; private: @@ -52,12 +53,14 @@ namespace PBQP { private: - class NodeEntry { + class NodeEntry : public llvm::ilist_node<NodeEntry> { + friend struct llvm::ilist_sentinel_traits<NodeEntry>; private: Vector costs; AdjEdgeList adjEdges; unsigned degree; void *data; + NodeEntry() : costs(0, 0) {} public: NodeEntry(const Vector &costs) : costs(costs), degree(0) {} Vector& getCosts() { return costs; } @@ -77,12 +80,14 @@ namespace PBQP { void* getData() { return data; } }; - class EdgeEntry { + class EdgeEntry : public llvm::ilist_node<EdgeEntry> { + friend struct llvm::ilist_sentinel_traits<EdgeEntry>; private: NodeItr node1, node2; Matrix costs; AdjEdgeItr node1AEItr, node2AEItr; void *data; + EdgeEntry() : costs(0, 0, 0) {} public: EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs) : node1(node1), node2(node2), costs(costs) {} diff --git a/include/llvm/CodeGen/PBQP/HeuristicSolver.h b/include/llvm/CodeGen/PBQP/HeuristicSolver.h index 35514f9..47e15b2 100644 --- a/include/llvm/CodeGen/PBQP/HeuristicSolver.h +++ b/include/llvm/CodeGen/PBQP/HeuristicSolver.h @@ -18,8 +18,8 @@ #include "Graph.h" #include "Solution.h" -#include <vector> #include <limits> +#include <vector> namespace PBQP { diff --git a/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h b/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h index a859e58..307d81e 100644 --- a/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h +++ b/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h @@ -18,9 +18,8 @@ #ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H #define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H -#include "../HeuristicSolver.h" #include "../HeuristicBase.h" - +#include "../HeuristicSolver.h" #include <limits> namespace PBQP { diff --git a/include/llvm/CodeGen/PBQP/Math.h b/include/llvm/CodeGen/PBQP/Math.h index e7598bf..4e51913 100644 --- a/include/llvm/CodeGen/PBQP/Math.h +++ b/include/llvm/CodeGen/PBQP/Math.h @@ -10,8 +10,8 @@ #ifndef LLVM_CODEGEN_PBQP_MATH_H #define LLVM_CODEGEN_PBQP_MATH_H -#include <cassert> #include <algorithm> +#include <cassert> #include <functional> namespace PBQP { diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index 57d9b95..b9f288b 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -14,9 +14,8 @@ #ifndef LLVM_CODEGEN_PBQP_SOLUTION_H #define LLVM_CODEGEN_PBQP_SOLUTION_H -#include "Math.h" #include "Graph.h" - +#include "Math.h" #include <map> namespace PBQP { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 7bd5764..0d02700 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -141,6 +141,10 @@ public: /// Add passes to lower exception handling for the code generator. void addPassesToHandleExceptions(); + /// Add pass to prepare the LLVM IR for code generation. This should be done + /// before exception handling preparation passes. + virtual void addCodeGenPrepare(); + /// Add common passes that perform LLVM IR to IR transforms in preparation for /// instruction selection. virtual void addISelPrepare(); @@ -237,6 +241,11 @@ protected: return false; } + /// addGCPasses - Add late codegen passes that analyze code for garbage + /// collection. This should return true if GC info should be printed after + /// these passes. + virtual bool addGCPasses(); + /// Add standard basic block placement passes. virtual void addBlockPlacement(); @@ -271,6 +280,12 @@ protected: /// List of target independent CodeGen pass IDs. namespace llvm { + /// \brief Create a basic TargetTransformInfo analysis pass. + /// + /// This pass implements the target transform info analysis using the target + /// independent information available to the LLVM code generator. + ImmutablePass *createBasicTargetTransformInfoPass(const TargetLowering *TLI); + /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a /// block that cannot be reached?). As such, a code generator should either @@ -288,9 +303,6 @@ namespace llvm { /// MachineLoopInfo - This pass is a loop analysis pass. extern char &MachineLoopInfoID; - /// MachineLoopRanges - This pass is an on-demand loop coverage analysis. - extern char &MachineLoopRangesID; - /// MachineDominators - This pass is a machine dominators analysis pass. extern char &MachineDominatorsID; diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index 7dab4f9..df74d088 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -14,7 +14,7 @@ #ifndef LLVM_CODEGEN_PSEUDOSOURCEVALUE_H #define LLVM_CODEGEN_PSEUDOSOURCEVALUE_H -#include "llvm/Value.h" +#include "llvm/IR/Value.h" namespace llvm { class MachineFrameInfo; @@ -50,7 +50,6 @@ namespace llvm { /// classof - Methods for support type inquiry through isa, cast, and /// dyn_cast: /// - static inline bool classof(const PseudoSourceValue *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == PseudoSourceValueVal || V->getValueID() == FixedStackPseudoSourceValueVal; @@ -90,9 +89,6 @@ namespace llvm { /// classof - Methods for support type inquiry through isa, cast, and /// dyn_cast: /// - static inline bool classof(const FixedStackPseudoSourceValue *) { - return true; - } static inline bool classof(const Value *V) { return V->getValueID() == FixedStackPseudoSourceValueVal; } diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index bce3ec7..b617c14 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -20,7 +20,6 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/PBQP/Graph.h" #include "llvm/CodeGen/PBQP/Solution.h" - #include <map> #include <set> @@ -29,6 +28,7 @@ namespace llvm { class LiveIntervals; class MachineFunction; class MachineLoopInfo; + class TargetRegisterInfo; /// This class wraps up a PBQP instance representing a register allocation /// problem, plus the structures necessary to map back from the PBQP solution @@ -109,8 +109,8 @@ namespace llvm { /// class to support additional constraints for your architecture. class PBQPBuilder { private: - PBQPBuilder(const PBQPBuilder&) {} - void operator=(const PBQPBuilder&) {} + PBQPBuilder(const PBQPBuilder&) LLVM_DELETED_FUNCTION; + void operator=(const PBQPBuilder&) LLVM_DELETED_FUNCTION; public: typedef std::set<unsigned> RegSet; diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h index 400e1f4..12bd1c6 100644 --- a/include/llvm/CodeGen/RegisterClassInfo.h +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -29,10 +29,10 @@ class RegisterClassInfo { unsigned Tag; unsigned NumRegs; bool ProperSubClass; - OwningArrayPtr<unsigned> Order; + OwningArrayPtr<MCPhysReg> Order; RCInfo() : Tag(0), NumRegs(0), ProperSubClass(false) {} - operator ArrayRef<unsigned>() const { + operator ArrayRef<MCPhysReg>() const { return makeArrayRef(Order.get(), NumRegs); } }; @@ -84,7 +84,7 @@ public: /// getOrder - Returns the preferred allocation order for RC. The order /// contains no reserved registers, and registers that alias callee saved /// registers come last. - ArrayRef<unsigned> getOrder(const TargetRegisterClass *RC) const { + ArrayRef<MCPhysReg> getOrder(const TargetRegisterClass *RC) const { return get(RC); } @@ -106,25 +106,6 @@ public: return CalleeSaved[N-1]; return 0; } - - /// isReserved - Returns true when PhysReg is a reserved register. - /// - /// Reserved registers may belong to an allocatable register class, but the - /// target has explicitly requested that they are not used. - /// - bool isReserved(unsigned PhysReg) const { - return Reserved.test(PhysReg); - } - - /// isAllocatable - Returns true when PhysReg belongs to an allocatable - /// register class and it hasn't been reserved. - /// - /// Allocatable registers may show up in the allocation order of some virtual - /// register, so a register allocator needs to track its liveness and - /// availability. - bool isAllocatable(unsigned PhysReg) const { - return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg); - } }; } // end namespace llvm diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index 2043155..2670180 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -15,13 +15,14 @@ #ifndef LLVM_CODEGEN_REGISTERPRESSURE_H #define LLVM_CODEGEN_REGISTERPRESSURE_H +#include "llvm/ADT/SparseSet.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/ADT/SparseSet.h" namespace llvm { class LiveIntervals; +class LiveInterval; class RegisterClassInfo; class MachineInstr; @@ -30,20 +31,26 @@ struct RegisterPressure { /// Map of max reg pressure indexed by pressure set ID, not class ID. std::vector<unsigned> MaxSetPressure; - /// List of live in registers. + /// List of live in virtual registers or physical register units. SmallVector<unsigned,8> LiveInRegs; SmallVector<unsigned,8> LiveOutRegs; /// Increase register pressure for each pressure set impacted by this register /// class. Normally called by RegPressureTracker, but may be called manually /// to account for live through (global liveness). - void increase(const TargetRegisterClass *RC, const TargetRegisterInfo *TRI); + /// + /// \param Reg is either a virtual register number or register unit number. + void increase(unsigned Reg, const TargetRegisterInfo *TRI, + const MachineRegisterInfo *MRI); /// Decrease register pressure for each pressure set impacted by this register /// class. This is only useful to account for spilling or rematerialization. - void decrease(const TargetRegisterClass *RC, const TargetRegisterInfo *TRI); + /// + /// \param Reg is either a virtual register number or register unit number. + void decrease(unsigned Reg, const TargetRegisterInfo *TRI, + const MachineRegisterInfo *MRI); - void dump(const TargetRegisterInfo *TRI); + void dump(const TargetRegisterInfo *TRI) const; }; /// RegisterPressure computed within a region of instructions delimited by @@ -116,6 +123,33 @@ struct RegPressureDelta { RegPressureDelta() {} }; +/// \brief A set of live virtual registers and physical register units. +/// +/// Virtual and physical register numbers require separate sparse sets, but most +/// of the RegisterPressureTracker handles them uniformly. +struct LiveRegSet { + SparseSet<unsigned> PhysRegs; + SparseSet<unsigned, VirtReg2IndexFunctor> VirtRegs; + + bool contains(unsigned Reg) { + if (TargetRegisterInfo::isVirtualRegister(Reg)) + return VirtRegs.count(Reg); + return PhysRegs.count(Reg); + } + + bool insert(unsigned Reg) { + if (TargetRegisterInfo::isVirtualRegister(Reg)) + return VirtRegs.insert(Reg).second; + return PhysRegs.insert(Reg).second; + } + + bool erase(unsigned Reg) { + if (TargetRegisterInfo::isVirtualRegister(Reg)) + return VirtRegs.erase(Reg); + return PhysRegs.erase(Reg); + } +}; + /// Track the current register pressure at some position in the instruction /// stream, and remember the high water mark within the region traversed. This /// does not automatically consider live-through ranges. The client may @@ -150,15 +184,15 @@ class RegPressureTracker { bool RequireIntervals; /// Register pressure corresponds to liveness before this instruction - /// iterator. It may point to the end of the block rather than an instruction. + /// iterator. It may point to the end of the block or a DebugValue rather than + /// an instruction. MachineBasicBlock::const_iterator CurrPos; /// Pressure map indexed by pressure set ID, not class ID. std::vector<unsigned> CurrSetPressure; - /// List of live registers. - SparseSet<unsigned> LivePhysRegs; - SparseSet<unsigned, VirtReg2IndexFunctor> LiveVirtRegs; + /// Set of live registers. + LiveRegSet LiveRegs; public: RegPressureTracker(IntervalPressure &rp) : @@ -171,8 +205,9 @@ public: const LiveIntervals *lis, const MachineBasicBlock *mbb, MachineBasicBlock::const_iterator pos); - /// Force liveness of registers. Particularly useful to initialize the - /// livein/out state of the tracker before the first call to advance/recede. + /// Force liveness of virtual registers or physical register + /// units. Particularly useful to initialize the livein/out state of the + /// tracker before the first call to advance/recede. void addLiveRegs(ArrayRef<unsigned> Regs); /// Get the MI position corresponding to this register pressure. @@ -184,6 +219,10 @@ public: // position changes while pressure does not. void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; } + /// \brief Get the SlotIndex for the first nondebug instruction including or + /// after the current position. + SlotIndex getCurrSlot() const; + /// Recede across the previous instruction. bool recede(); @@ -197,16 +236,14 @@ public: /// This result is complete if either advance() or recede() has returned true, /// or if closeRegion() was explicitly invoked. RegisterPressure &getPressure() { return P; } + const RegisterPressure &getPressure() const { return P; } /// Get the register set pressure at the current position, which may be less /// than the pressure across the traversed region. std::vector<unsigned> &getRegSetPressureAtPos() { return CurrSetPressure; } - void discoverPhysLiveIn(unsigned Reg); - void discoverPhysLiveOut(unsigned Reg); - - void discoverVirtLiveIn(unsigned Reg); - void discoverVirtLiveOut(unsigned Reg); + void discoverLiveOut(unsigned Reg); + void discoverLiveIn(unsigned Reg); bool isTopClosed() const; bool isBottomClosed() const; @@ -267,12 +304,13 @@ public: return getDownwardPressure(MI, PressureResult, MaxPressureResult); } + void dump() const; + protected: - void increasePhysRegPressure(ArrayRef<unsigned> Regs); - void decreasePhysRegPressure(ArrayRef<unsigned> Regs); + const LiveInterval *getInterval(unsigned Reg) const; - void increaseVirtRegPressure(ArrayRef<unsigned> Regs); - void decreaseVirtRegPressure(ArrayRef<unsigned> Regs); + void increaseRegPressure(ArrayRef<unsigned> Regs); + void decreaseRegPressure(ArrayRef<unsigned> Regs); void bumpUpwardPressure(const MachineInstr *MI); void bumpDownwardPressure(const MachineInstr *MI); diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 3986a8d..6604d4c 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -17,8 +17,9 @@ #ifndef LLVM_CODEGEN_REGISTER_SCAVENGING_H #define LLVM_CODEGEN_REGISTER_SCAVENGING_H -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/BitVector.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" namespace llvm { @@ -59,10 +60,6 @@ class RegScavenger { /// BitVector CalleeSavedRegs; - /// ReservedRegs - A bitvector of reserved registers. - /// - BitVector ReservedRegs; - /// RegsAvailable - The current state of all the physical registers immediately /// before MBBI. One bit per physical register. If bit is set that means it's /// available, unset means the register is currently being used. @@ -130,12 +127,14 @@ public: void setUsed(unsigned Reg); private: /// isReserved - Returns true if a register is reserved. It is never "unused". - bool isReserved(unsigned Reg) const { return ReservedRegs.test(Reg); } + bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); } - /// isUsed / isUnused - Test if a register is currently being used. + /// isUsed - Test if a register is currently being used. When called by the + /// isAliasUsed function, we only check isReserved if this is the original + /// register, not an alias register. /// - bool isUsed(unsigned Reg) const { - return !RegsAvailable.test(Reg) || ReservedRegs.test(Reg); + bool isUsed(unsigned Reg, bool CheckReserved = true) const { + return !RegsAvailable.test(Reg) || (CheckReserved && isReserved(Reg)); } /// isAliasUsed - Is Reg or an alias currently in use? diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h index 56b5855..66a6039 100644 --- a/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -18,8 +18,8 @@ #define RESOURCE_PRIORITY_QUEUE_H #include "llvm/CodeGen/DFAPacketizer.h" -#include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 4bfd4ab..1a9dc1c 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -86,100 +86,126 @@ namespace RTLIB { ADD_F32, ADD_F64, ADD_F80, + ADD_F128, ADD_PPCF128, SUB_F32, SUB_F64, SUB_F80, + SUB_F128, SUB_PPCF128, MUL_F32, MUL_F64, MUL_F80, + MUL_F128, MUL_PPCF128, DIV_F32, DIV_F64, DIV_F80, + DIV_F128, DIV_PPCF128, REM_F32, REM_F64, REM_F80, + REM_F128, REM_PPCF128, FMA_F32, FMA_F64, FMA_F80, + FMA_F128, FMA_PPCF128, POWI_F32, POWI_F64, POWI_F80, + POWI_F128, POWI_PPCF128, SQRT_F32, SQRT_F64, SQRT_F80, + SQRT_F128, SQRT_PPCF128, LOG_F32, LOG_F64, LOG_F80, + LOG_F128, LOG_PPCF128, LOG2_F32, LOG2_F64, LOG2_F80, + LOG2_F128, LOG2_PPCF128, LOG10_F32, LOG10_F64, LOG10_F80, + LOG10_F128, LOG10_PPCF128, EXP_F32, EXP_F64, EXP_F80, + EXP_F128, EXP_PPCF128, EXP2_F32, EXP2_F64, EXP2_F80, + EXP2_F128, EXP2_PPCF128, SIN_F32, SIN_F64, SIN_F80, + SIN_F128, SIN_PPCF128, COS_F32, COS_F64, COS_F80, + COS_F128, COS_PPCF128, POW_F32, POW_F64, POW_F80, + POW_F128, POW_PPCF128, CEIL_F32, CEIL_F64, CEIL_F80, + CEIL_F128, CEIL_PPCF128, TRUNC_F32, TRUNC_F64, TRUNC_F80, + TRUNC_F128, TRUNC_PPCF128, RINT_F32, RINT_F64, RINT_F80, + RINT_F128, RINT_PPCF128, NEARBYINT_F32, NEARBYINT_F64, NEARBYINT_F80, + NEARBYINT_F128, NEARBYINT_PPCF128, FLOOR_F32, FLOOR_F64, FLOOR_F80, + FLOOR_F128, FLOOR_PPCF128, COPYSIGN_F32, COPYSIGN_F64, COPYSIGN_F80, + COPYSIGN_F128, COPYSIGN_PPCF128, // CONVERSION + FPEXT_F64_F128, + FPEXT_F32_F128, FPEXT_F32_F64, FPEXT_F16_F32, FPROUND_F32_F16, FPROUND_F64_F32, FPROUND_F80_F32, + FPROUND_F128_F32, FPROUND_PPCF128_F32, FPROUND_F80_F64, + FPROUND_F128_F64, FPROUND_PPCF128_F64, FPTOSINT_F32_I8, FPTOSINT_F32_I16, @@ -194,6 +220,9 @@ namespace RTLIB { FPTOSINT_F80_I32, FPTOSINT_F80_I64, FPTOSINT_F80_I128, + FPTOSINT_F128_I32, + FPTOSINT_F128_I64, + FPTOSINT_F128_I128, FPTOSINT_PPCF128_I32, FPTOSINT_PPCF128_I64, FPTOSINT_PPCF128_I128, @@ -210,51 +239,68 @@ namespace RTLIB { FPTOUINT_F80_I32, FPTOUINT_F80_I64, FPTOUINT_F80_I128, + FPTOUINT_F128_I32, + FPTOUINT_F128_I64, + FPTOUINT_F128_I128, FPTOUINT_PPCF128_I32, FPTOUINT_PPCF128_I64, FPTOUINT_PPCF128_I128, SINTTOFP_I32_F32, SINTTOFP_I32_F64, SINTTOFP_I32_F80, + SINTTOFP_I32_F128, SINTTOFP_I32_PPCF128, SINTTOFP_I64_F32, SINTTOFP_I64_F64, SINTTOFP_I64_F80, + SINTTOFP_I64_F128, SINTTOFP_I64_PPCF128, SINTTOFP_I128_F32, SINTTOFP_I128_F64, SINTTOFP_I128_F80, + SINTTOFP_I128_F128, SINTTOFP_I128_PPCF128, UINTTOFP_I32_F32, UINTTOFP_I32_F64, UINTTOFP_I32_F80, + UINTTOFP_I32_F128, UINTTOFP_I32_PPCF128, UINTTOFP_I64_F32, UINTTOFP_I64_F64, UINTTOFP_I64_F80, + UINTTOFP_I64_F128, UINTTOFP_I64_PPCF128, UINTTOFP_I128_F32, UINTTOFP_I128_F64, UINTTOFP_I128_F80, + UINTTOFP_I128_F128, UINTTOFP_I128_PPCF128, // COMPARISON OEQ_F32, OEQ_F64, + OEQ_F128, UNE_F32, UNE_F64, + UNE_F128, OGE_F32, OGE_F64, + OGE_F128, OLT_F32, OLT_F64, + OLT_F128, OLE_F32, OLE_F64, + OLE_F128, OGT_F32, OGT_F64, + OGT_F128, UO_F32, UO_F64, + UO_F128, O_F32, O_F64, + O_F128, // MEMORY MEMCPY, diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 2567a65..aa91b03 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -16,13 +16,13 @@ #ifndef LLVM_CODEGEN_SCHEDULEDAG_H #define LLVM_CODEGEN_SCHEDULEDAG_H -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetLowering.h" namespace llvm { class AliasAnalysis; @@ -31,6 +31,7 @@ namespace llvm { class MachineFunction; class MachineRegisterInfo; class MachineInstr; + struct MCSchedClassDesc; class TargetRegisterInfo; class ScheduleDAG; class SDNode; @@ -52,6 +53,14 @@ namespace llvm { Order ///< Any other ordering dependency. }; + enum OrderKind { + Barrier, ///< An unknown scheduling barrier. + MayAliasMem, ///< Nonvolatile load/Store instructions that may alias. + MustAliasMem, ///< Nonvolatile load/Store instructions that must alias. + Artificial, ///< Arbitrary weak DAG edge (no actual dependence). + Cluster ///< Weak DAG edge linking a chain of clustered instrs. + }; + private: /// Dep - A pointer to the depending/depended-on SUnit, and an enum /// indicating the kind of the dependency. @@ -65,20 +74,7 @@ namespace llvm { unsigned Reg; /// Order - Additional information about Order dependencies. - struct { - /// isNormalMemory - True if both sides of the dependence - /// access memory in non-volatile and fully modeled ways. - bool isNormalMemory : 1; - - /// isMustAlias - True if both sides of the dependence are known to - /// access the same memory. - bool isMustAlias : 1; - - /// isArtificial - True if this is an artificial dependency, meaning - /// it is not necessary for program correctness, and may be safely - /// deleted if necessary. - bool isArtificial : 1; - } Order; + unsigned OrdKind; // enum OrderKind } Contents; /// Latency - The time associated with this edge. Often this is just @@ -86,6 +82,9 @@ namespace llvm { /// models may provide additional information about specific edges. unsigned Latency; /// Record MinLatency seperately from "expected" Latency. + /// + /// FIXME: this field is not packed on LP64. Convert to 16-bit DAG edge + /// latency after introducing saturating truncation. unsigned MinLatency; public: @@ -95,28 +94,28 @@ namespace llvm { SDep() : Dep(0, Data) {} /// SDep - Construct an SDep with the specified values. - SDep(SUnit *S, Kind kind, unsigned latency = 1, unsigned Reg = 0, - bool isNormalMemory = false, bool isMustAlias = false, - bool isArtificial = false) - : Dep(S, kind), Contents(), Latency(latency), MinLatency(latency) { + SDep(SUnit *S, Kind kind, unsigned Reg) + : Dep(S, kind), Contents() { switch (kind) { + default: + llvm_unreachable("Reg given for non-register dependence!"); case Anti: case Output: assert(Reg != 0 && "SDep::Anti and SDep::Output must use a non-zero Reg!"); - // fall through - case Data: - assert(!isMustAlias && "isMustAlias only applies with SDep::Order!"); - assert(!isArtificial && "isArtificial only applies with SDep::Order!"); Contents.Reg = Reg; + Latency = 0; break; - case Order: - assert(Reg == 0 && "Reg given for non-register dependence!"); - Contents.Order.isNormalMemory = isNormalMemory; - Contents.Order.isMustAlias = isMustAlias; - Contents.Order.isArtificial = isArtificial; + case Data: + Contents.Reg = Reg; + Latency = 1; break; } + MinLatency = Latency; + } + SDep(SUnit *S, OrderKind kind) + : Dep(S, Order), Contents(), Latency(0), MinLatency(0) { + Contents.OrdKind = kind; } /// Return true if the specified SDep is equivalent except for latency. @@ -128,10 +127,7 @@ namespace llvm { case Output: return Contents.Reg == Other.Contents.Reg; case Order: - return Contents.Order.isNormalMemory == - Other.Contents.Order.isNormalMemory && - Contents.Order.isMustAlias == Other.Contents.Order.isMustAlias && - Contents.Order.isArtificial == Other.Contents.Order.isArtificial; + return Contents.OrdKind == Other.Contents.OrdKind; } llvm_unreachable("Invalid dependency kind!"); } @@ -194,20 +190,35 @@ namespace llvm { /// memory accesses where both sides of the dependence access memory /// in non-volatile and fully modeled ways. bool isNormalMemory() const { - return getKind() == Order && Contents.Order.isNormalMemory; + return getKind() == Order && (Contents.OrdKind == MayAliasMem + || Contents.OrdKind == MustAliasMem); } /// isMustAlias - Test if this is an Order dependence that is marked /// as "must alias", meaning that the SUnits at either end of the edge /// have a memory dependence on a known memory location. bool isMustAlias() const { - return getKind() == Order && Contents.Order.isMustAlias; + return getKind() == Order && Contents.OrdKind == MustAliasMem; + } + + /// isWeak - Test if this a weak dependence. Weak dependencies are + /// considered DAG edges for height computation and other heuristics, but do + /// not force ordering. Breaking a weak edge may require the scheduler to + /// compensate, for example by inserting a copy. + bool isWeak() const { + return getKind() == Order && Contents.OrdKind == Cluster; } /// isArtificial - Test if this is an Order dependence that is marked /// as "artificial", meaning it isn't necessary for correctness. bool isArtificial() const { - return getKind() == Order && Contents.Order.isArtificial; + return getKind() == Order && Contents.OrdKind == Artificial; + } + + /// isCluster - Test if this is an Order dependence that is marked + /// as "cluster", meaning it is artificial and wants to be adjacent. + bool isCluster() const { + return getKind() == Order && Contents.OrdKind == Cluster; } /// isAssignedRegDep - Test if this is a Data dependence that is @@ -254,6 +265,8 @@ namespace llvm { // this node was cloned. // (SD scheduling only) + const MCSchedClassDesc *SchedClass; // NULL or resolved SchedClass. + // Preds/Succs - The SUnits before/after us in the graph. SmallVector<SDep, 4> Preds; // All sunit predecessors. SmallVector<SDep, 4> Succs; // All sunit successors. @@ -269,6 +282,8 @@ namespace llvm { unsigned NumSuccs; // # of SDep::Data sucss. unsigned NumPredsLeft; // # of preds not scheduled. unsigned NumSuccsLeft; // # of succs not scheduled. + unsigned WeakPredsLeft; // # of weak preds not scheduled. + unsigned WeakSuccsLeft; // # of weak succs not scheduled. unsigned short NumRegDefsLeft; // # of reg defs with no scheduled use. unsigned short Latency; // Node latency. bool isVRegCycle : 1; // May use and def the same vreg. @@ -301,41 +316,41 @@ namespace llvm { /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent /// an SDNode and any nodes flagged to it. SUnit(SDNode *node, unsigned nodenum) - : Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), + : Node(node), Instr(0), OrigNode(0), SchedClass(0), NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), - isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), - isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), - isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isScheduleLow(false), isCloned(false), - SchedulingPref(Sched::None), + NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), + Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), + isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), + hasPhysRegClobbers(false), isPending(false), isAvailable(false), + isScheduled(false), isScheduleHigh(false), isScheduleLow(false), + isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} /// SUnit - Construct an SUnit for post-regalloc scheduling to represent /// a MachineInstr. SUnit(MachineInstr *instr, unsigned nodenum) - : Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), + : Node(0), Instr(instr), OrigNode(0), SchedClass(0), NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), - isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), - isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), - isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isScheduleLow(false), isCloned(false), - SchedulingPref(Sched::None), + NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), + Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), + isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), + hasPhysRegClobbers(false), isPending(false), isAvailable(false), + isScheduled(false), isScheduleHigh(false), isScheduleLow(false), + isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} /// SUnit - Construct a placeholder SUnit. SUnit() - : Node(0), Instr(0), OrigNode(0), NodeNum(~0u), + : Node(0), Instr(0), OrigNode(0), SchedClass(0), NodeNum(~0u), NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), - isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), - isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), - isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isScheduleLow(false), isCloned(false), - SchedulingPref(Sched::None), + NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), + Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), + isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), + hasPhysRegClobbers(false), isPending(false), isAvailable(false), + isScheduled(false), isScheduleHigh(false), isScheduleLow(false), + isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -374,7 +389,7 @@ namespace llvm { /// addPred - This adds the specified edge as a pred of the current node if /// not already. It also adds the current node as a successor of the /// specified node. - bool addPred(const SDep &D); + bool addPred(const SDep &D, bool Required = true); /// removePred - This removes the specified edge as a pred of the current /// node if it exists. It also removes the current node as a successor of @@ -570,16 +585,6 @@ namespace llvm { unsigned VerifyScheduledDAG(bool isBottomUp); #endif - protected: - /// ComputeLatency - Compute node latency. - /// - virtual void computeLatency(SUnit *SU) = 0; - - /// ForceUnitLatencies - Return true if all scheduling edges should be given - /// a latency value of one. The default is to return false; schedulers may - /// override this as needed. - virtual bool forceUnitLatencies() const { return false; } - private: // Return the MCInstrDesc of this SDNode or NULL. const MCInstrDesc *getNodeDesc(const SDNode *Node) const; @@ -666,6 +671,7 @@ namespace llvm { class ScheduleDAGTopologicalSort { /// SUnits - A reference to the ScheduleDAG's SUnits. std::vector<SUnit> &SUnits; + SUnit *ExitSU; /// Index2Node - Maps topological index to the node number. std::vector<int> Index2Node; @@ -687,7 +693,7 @@ namespace llvm { void Allocate(int n, int index); public: - explicit ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits); + ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits, SUnit *ExitSU); /// InitDAGTopologicalSorting - create the initial topological /// ordering from the DAG to be scheduled. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 8b52b5a..ffc442e 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -15,13 +15,14 @@ #ifndef SCHEDULEDAGINSTRS_H #define SCHEDULEDAGINSTRS_H +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SparseSet.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/TargetSchedule.h" #include "llvm/Support/Compiler.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SparseSet.h" #include <map> namespace llvm { @@ -30,72 +31,6 @@ namespace llvm { class LiveIntervals; class RegPressureTracker; - /// LoopDependencies - This class analyzes loop-oriented register - /// dependencies, which are used to guide scheduling decisions. - /// For example, loop induction variable increments should be - /// scheduled as soon as possible after the variable's last use. - /// - class LoopDependencies { - const MachineDominatorTree &MDT; - - public: - typedef std::map<unsigned, std::pair<const MachineOperand *, unsigned> > - LoopDeps; - LoopDeps Deps; - - LoopDependencies(const MachineDominatorTree &mdt) : MDT(mdt) {} - - /// VisitLoop - Clear out any previous state and analyze the given loop. - /// - void VisitLoop(const MachineLoop *Loop) { - assert(Deps.empty() && "stale loop dependencies"); - - MachineBasicBlock *Header = Loop->getHeader(); - SmallSet<unsigned, 8> LoopLiveIns; - for (MachineBasicBlock::livein_iterator LI = Header->livein_begin(), - LE = Header->livein_end(); LI != LE; ++LI) - LoopLiveIns.insert(*LI); - - const MachineDomTreeNode *Node = MDT.getNode(Header); - const MachineBasicBlock *MBB = Node->getBlock(); - assert(Loop->contains(MBB) && - "Loop does not contain header!"); - VisitRegion(Node, MBB, Loop, LoopLiveIns); - } - - private: - void VisitRegion(const MachineDomTreeNode *Node, - const MachineBasicBlock *MBB, - const MachineLoop *Loop, - const SmallSet<unsigned, 8> &LoopLiveIns) { - unsigned Count = 0; - for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); - I != E; ++I) { - const MachineInstr *MI = I; - if (MI->isDebugValue()) - continue; - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || !MO.isUse()) - continue; - unsigned MOReg = MO.getReg(); - if (LoopLiveIns.count(MOReg)) - Deps.insert(std::make_pair(MOReg, std::make_pair(&MO, Count))); - } - ++Count; // Not every iteration due to dbg_value above. - } - - const std::vector<MachineDomTreeNode*> &Children = Node->getChildren(); - for (std::vector<MachineDomTreeNode*>::const_iterator I = - Children.begin(), E = Children.end(); I != E; ++I) { - const MachineDomTreeNode *ChildNode = *I; - MachineBasicBlock *ChildBlock = ChildNode->getBlock(); - if (Loop->contains(ChildBlock)) - VisitRegion(ChildNode, ChildBlock, Loop, LoopLiveIns); - } - } - }; - /// An individual mapping from virtual register number to SUnit. struct VReg2SUnit { unsigned VirtReg; @@ -176,11 +111,13 @@ namespace llvm { const MachineLoopInfo &MLI; const MachineDominatorTree &MDT; const MachineFrameInfo *MFI; - const InstrItineraryData *InstrItins; /// Live Intervals provides reaching defs in preRA scheduling. LiveIntervals *LIS; + /// TargetSchedModel provides an interface to the machine model. + TargetSchedModel SchedModel; + /// isPostRA flag indicates vregs cannot be present. bool IsPostRA; @@ -232,10 +169,6 @@ namespace llvm { /// to minimize construction/destruction. std::vector<SUnit *> PendingLoads; - /// LoopRegs - Track which registers are used for loop-carried dependencies. - /// - LoopDependencies LoopRegs; - /// DbgValues - Remember instruction that precedes DBG_VALUE. /// These are generated by buildSchedGraph but persist so they can be /// referenced when emitting the final schedule. @@ -253,6 +186,16 @@ namespace llvm { virtual ~ScheduleDAGInstrs() {} + /// \brief Get the machine model for instruction scheduling. + const TargetSchedModel *getSchedModel() const { return &SchedModel; } + + /// \brief Resolve and cache a resolved scheduling class for an SUnit. + const MCSchedClassDesc *getSchedClass(SUnit *SU) const { + if (!SU->SchedClass) + SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr()); + return SU->SchedClass; + } + /// begin - Return an iterator to the top of the current scheduling region. MachineBasicBlock::iterator begin() const { return RegionBegin; } @@ -293,10 +236,6 @@ namespace llvm { /// used by instructions in the fallthrough block. void addSchedBarrierDeps(); - /// computeLatency - Compute node latency. - /// - virtual void computeLatency(SUnit *SU); - /// schedule - Order nodes according to selected style, filling /// in the Sequence member. /// diff --git a/include/llvm/CodeGen/ScheduleDFS.h b/include/llvm/CodeGen/ScheduleDFS.h new file mode 100644 index 0000000..fbbadd9 --- /dev/null +++ b/include/llvm/CodeGen/ScheduleDFS.h @@ -0,0 +1,152 @@ +//===- ScheduleDAGILP.h - ILP metric for ScheduleDAGInstrs ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Definition of an ILP metric for machine level instruction scheduling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCHEDULEDAGILP_H +#define LLVM_CODEGEN_SCHEDULEDAGILP_H + +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Support/DataTypes.h" +#include <vector> + +namespace llvm { + +class raw_ostream; +class IntEqClasses; +class ScheduleDAGInstrs; +class SUnit; + +/// \brief Represent the ILP of the subDAG rooted at a DAG node. +/// +/// When computed using bottom-up DFS, this metric assumes that the DAG is a +/// forest of trees with roots at the bottom of the schedule branching upward. +struct ILPValue { + unsigned InstrCount; + /// Length may either correspond to depth or height, depending on direction, + /// and cycles or nodes depending on context. + unsigned Length; + + ILPValue(unsigned count, unsigned length): + InstrCount(count), Length(length) {} + + // Order by the ILP metric's value. + bool operator<(ILPValue RHS) const { + return (uint64_t)InstrCount * RHS.Length + < (uint64_t)Length * RHS.InstrCount; + } + bool operator>(ILPValue RHS) const { + return RHS < *this; + } + bool operator<=(ILPValue RHS) const { + return (uint64_t)InstrCount * RHS.Length + <= (uint64_t)Length * RHS.InstrCount; + } + bool operator>=(ILPValue RHS) const { + return RHS <= *this; + } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + void print(raw_ostream &OS) const; + + void dump() const; +#endif +}; + +/// \brief Compute the values of each DAG node for various metrics during DFS. +/// +/// ILPValues summarize the DAG subtree rooted at each node up to +/// SubtreeLimit. ILPValues are also valid for interior nodes of a subtree, not +/// just the root. +class SchedDFSResult { + friend class SchedDFSImpl; + + /// \brief Per-SUnit data computed during DFS for various metrics. + struct NodeData { + unsigned InstrCount; + unsigned SubtreeID; + + NodeData(): InstrCount(0), SubtreeID(0) {} + }; + + /// \brief Record a connection between subtrees and the connection level. + struct Connection { + unsigned TreeID; + unsigned Level; + + Connection(unsigned tree, unsigned level): TreeID(tree), Level(level) {} + }; + + bool IsBottomUp; + unsigned SubtreeLimit; + /// DFS results for each SUnit in this DAG. + std::vector<NodeData> DFSData; + + // For each subtree discovered during DFS, record its connections to other + // subtrees. + std::vector<SmallVector<Connection, 4> > SubtreeConnections; + + /// Cache the current connection level of each subtree. + /// This mutable array is updated during scheduling. + std::vector<unsigned> SubtreeConnectLevels; + +public: + SchedDFSResult(bool IsBU, unsigned lim) + : IsBottomUp(IsBU), SubtreeLimit(lim) {} + + /// \brief Clear the results. + void clear() { + DFSData.clear(); + SubtreeConnections.clear(); + SubtreeConnectLevels.clear(); + } + + /// \brief Initialize the result data with the size of the DAG. + void resize(unsigned NumSUnits) { + DFSData.resize(NumSUnits); + } + + /// \brief Compute various metrics for the DAG with given roots. + void compute(ArrayRef<SUnit *> Roots); + + /// \brief Get the ILP value for a DAG node. + /// + /// A leaf node has an ILP of 1/1. + ILPValue getILP(const SUnit *SU) { + return ILPValue(DFSData[SU->NodeNum].InstrCount, 1 + SU->getDepth()); + } + + /// \brief The number of subtrees detected in this DAG. + unsigned getNumSubtrees() const { return SubtreeConnectLevels.size(); } + + /// \brief Get the ID of the subtree the given DAG node belongs to. + unsigned getSubtreeID(const SUnit *SU) { + return DFSData[SU->NodeNum].SubtreeID; + } + + /// \brief Get the connection level of a subtree. + /// + /// For bottom-up trees, the connection level is the latency depth (in cycles) + /// of the deepest connection to another subtree. + unsigned getSubtreeLevel(unsigned SubtreeID) { + return SubtreeConnectLevels[SubtreeID]; + } + + /// \brief Scheduler callback to update SubtreeConnectLevels when a tree is + /// initially scheduled. + void scheduleTree(unsigned SubtreeID); +}; + +raw_ostream &operator<<(raw_ostream &OS, const ILPValue &Val); + +} // namespace llvm + +#endif diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h index a582b0c..836b73a 100644 --- a/include/llvm/CodeGen/SchedulerRegistry.h +++ b/include/llvm/CodeGen/SchedulerRegistry.h @@ -102,6 +102,11 @@ ScheduleDAGSDNodes *createVLIWDAGScheduler(SelectionDAGISel *IS, ScheduleDAGSDNodes *createDefaultScheduler(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel); +/// createDAGLinearizer - This creates a "no-scheduling" scheduler which +/// linearize the DAG using topological order. +ScheduleDAGSDNodes *createDAGLinearizer(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + } // end namespace llvm #endif diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h index 060e89a..c2103fb 100644 --- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -18,7 +18,6 @@ #include "llvm/CodeGen/ScheduleHazardRecognizer.h" #include "llvm/Support/DataTypes.h" - #include <cassert> #include <cstring> diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 1ccfe54..c5cc8f5 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -15,16 +15,17 @@ #ifndef LLVM_CODEGEN_SELECTIONDAG_H #define LLVM_CODEGEN_SELECTIONDAG_H -#include "llvm/ADT/ilist.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/ilist.h" +#include "llvm/CodeGen/DAGCombine.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/Support/RecyclingAllocator.h" #include "llvm/Target/TargetMachine.h" #include <cassert> -#include <vector> #include <map> #include <string> +#include <vector> namespace llvm { @@ -36,6 +37,7 @@ class SDNodeOrdering; class SDDbgValue; class TargetLowering; class TargetSelectionDAGInfo; +class TargetTransformInfo; template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> { private: @@ -73,8 +75,8 @@ class SDDbgInfo { SmallVector<SDDbgValue*, 32> ByvalParmDbgValues; DenseMap<const SDNode*, SmallVector<SDDbgValue*, 2> > DbgValMap; - void operator=(const SDDbgInfo&); // Do not implement. - SDDbgInfo(const SDDbgInfo&); // Do not implement. + void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION; + SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION; public: SDDbgInfo() {} @@ -111,13 +113,6 @@ public: DbgIterator ByvalParmDbgEnd() { return ByvalParmDbgValues.end(); } }; -enum CombineLevel { - BeforeLegalizeTypes, - AfterLegalizeTypes, - AfterLegalizeVectorOps, - AfterLegalizeDAG -}; - class SelectionDAG; void checkForCycles(const SDNode *N); void checkForCycles(const SelectionDAG *DAG); @@ -137,6 +132,7 @@ class SelectionDAG { const TargetMachine &TM; const TargetLowering &TLI; const TargetSelectionDAGInfo &TSI; + const TargetTransformInfo *TTI; MachineFunction *MF; LLVMContext *Context; CodeGenOpt::Level OptLevel; @@ -222,8 +218,8 @@ private: DenseSet<SDNode *> &visited, int level, bool &printed); - void operator=(const SelectionDAG&); // Do not implement. - SelectionDAG(const SelectionDAG&); // Do not implement. + void operator=(const SelectionDAG&) LLVM_DELETED_FUNCTION; + SelectionDAG(const SelectionDAG&) LLVM_DELETED_FUNCTION; public: explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level); @@ -232,7 +228,7 @@ public: /// init - Prepare this SelectionDAG to process code in the given /// MachineFunction. /// - void init(MachineFunction &mf); + void init(MachineFunction &mf, const TargetTransformInfo *TTI); /// clear - Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -243,6 +239,7 @@ public: const TargetMachine &getTarget() const { return TM; } const TargetLowering &getTargetLoweringInfo() const { return TLI; } const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } + const TargetTransformInfo *getTargetTransformInfo() const { return TTI; } LLVMContext *getContext() const {return Context; } /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. @@ -437,7 +434,13 @@ public: SDValue getRegisterMask(const uint32_t *RegMask); SDValue getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label); SDValue getBlockAddress(const BlockAddress *BA, EVT VT, - bool isTarget = false, unsigned char TargetFlags = 0); + int64_t Offset = 0, bool isTarget = false, + unsigned char TargetFlags = 0); + SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, + int64_t Offset = 0, + unsigned char TargetFlags = 0) { + return getBlockAddress(BA, VT, Offset, true, TargetFlags); + } SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N) { return getNode(ISD::CopyToReg, dl, MVT::Other, Chain, diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index c42f655..16aacc0 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -15,10 +15,10 @@ #ifndef LLVM_CODEGEN_SELECTIONDAG_ISEL_H #define LLVM_CODEGEN_SELECTIONDAG_ISEL_H -#include "llvm/BasicBlock.h" -#include "llvm/Pass.h" -#include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/Pass.h" namespace llvm { class FastISel; @@ -31,6 +31,7 @@ namespace llvm { class TargetLowering; class TargetLibraryInfo; class TargetInstrInfo; + class TargetTransformInfo; class FunctionLoweringInfo; class ScheduleHazardRecognizer; class GCFunctionInfo; @@ -44,6 +45,7 @@ public: const TargetMachine &TM; const TargetLowering &TLI; const TargetLibraryInfo *LibInfo; + const TargetTransformInfo *TTI; FunctionLoweringInfo *FuncInfo; MachineFunction *MF; MachineRegisterInfo *RegInfo; diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 3bea2de..2c34b4f 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -19,20 +19,20 @@ #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H #define LLVM_CODEGEN_SELECTIONDAGNODES_H -#include "llvm/Constants.h" -#include "llvm/Instructions.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ilist_node.h" #include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" +#include "llvm/Support/MathExtras.h" #include <cassert> namespace llvm { @@ -49,7 +49,7 @@ template <typename T> struct simplify_type; template <typename T> struct ilist_traits; void checkForCycles(const SDNode *N); - + /// SDVTList - This represents a list of ValueType's that has been intern'd by /// a SelectionDAG. Instances of this simple value class are returned by /// SelectionDAG::getVTList(...). @@ -108,7 +108,7 @@ public: void setNode(SDNode *N) { Node = N; } inline SDNode *operator->() const { return Node; } - + bool operator==(const SDValue &O) const { return Node == O.Node && ResNo == O.ResNo; } @@ -130,6 +130,11 @@ public: /// inline EVT getValueType() const; + /// Return the simple ValueType of the referenced return value. + MVT getSimpleValueType() const { + return getValueType().getSimpleVT(); + } + /// getValueSizeInBits - Returns the size of the value in bits. /// unsigned getValueSizeInBits() const { @@ -216,8 +221,8 @@ class SDUse { /// this operand. SDUse **Prev, *Next; - SDUse(const SDUse &U); // Do not implement - void operator=(const SDUse &U); // Do not implement + SDUse(const SDUse &U) LLVM_DELETED_FUNCTION; + void operator=(const SDUse &U) LLVM_DELETED_FUNCTION; public: SDUse() : Val(), User(NULL), Prev(NULL), Next(NULL) {} @@ -525,7 +530,7 @@ public: /// NOTE: This is still very expensive. Use carefully. bool hasPredecessorHelper(const SDNode *N, SmallPtrSet<const SDNode *, 32> &Visited, - SmallVector<const SDNode *, 16> &Worklist) const; + SmallVector<const SDNode *, 16> &Worklist) const; /// getNumOperands - Return the number of values used by this operation. /// @@ -595,6 +600,12 @@ public: return ValueList[ResNo]; } + /// Return the type of a specified result as a simple type. + /// + MVT getSimpleValueType(unsigned ResNo) const { + return getValueType(ResNo).getSimpleVT(); + } + /// getValueSizeInBits - Returns MVT::getSizeInBits(getValueType(ResNo)). /// unsigned getValueSizeInBits(unsigned ResNo) const { @@ -662,9 +673,6 @@ public: /// void dumprWithDepth(const SelectionDAG *G = 0, unsigned depth = 100) const; - - static bool classof(const SDNode *) { return true; } - /// Profile - Gather unique data for the node. /// void Profile(FoldingSetNodeID &ID) const; @@ -956,7 +964,12 @@ public: const MachinePointerInfo &getPointerInfo() const { return MMO->getPointerInfo(); } - + + /// getAddressSpace - Return the address space for the associated pointer + unsigned getAddressSpace() const { + return getPointerInfo().getAddrSpace(); + } + /// refineAlignment - Update this MemSDNode's MachineMemOperand information /// to reflect the alignment of NewMMO, if it has a greater alignment. /// This must only be used when the new alignment applies to all users of @@ -971,7 +984,6 @@ public: } // Methods to support isa and dyn_cast - static bool classof(const MemSDNode *) { return true; } static bool classof(const SDNode *N) { // For some targets, we lower some target intrinsics to a MemIntrinsicNode // with either an intrinsic or a target opcode. @@ -1056,7 +1068,6 @@ public: } // Methods to support isa and dyn_cast - static bool classof(const AtomicSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::ATOMIC_CMP_SWAP || N->getOpcode() == ISD::ATOMIC_SWAP || @@ -1088,7 +1099,6 @@ public: } // Methods to support isa and dyn_cast - static bool classof(const MemIntrinsicSDNode *) { return true; } static bool classof(const SDNode *N) { // We lower some target intrinsics to their target opcode // early a node with a target opcode can be of this class @@ -1143,7 +1153,6 @@ public: } static bool isSplatMask(const int *Mask, EVT VT); - static bool classof(const ShuffleVectorSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::VECTOR_SHUFFLE; } @@ -1167,7 +1176,6 @@ public: bool isNullValue() const { return Value->isNullValue(); } bool isAllOnesValue() const { return Value->isAllOnesValue(); } - static bool classof(const ConstantSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::Constant || N->getOpcode() == ISD::TargetConstant; @@ -1202,9 +1210,6 @@ public: /// have to duplicate its logic everywhere it's called. bool isExactlyValue(double V) const { bool ignored; - // convert is not supported on this type - if (&Value->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) - return false; APFloat Tmp(V); Tmp.convert(Value->getValueAPF().getSemantics(), APFloat::rmNearestTiesToEven, &ignored); @@ -1214,7 +1219,6 @@ public: static bool isValueValidForType(EVT VT, const APFloat& Val); - static bool classof(const ConstantFPSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::ConstantFP || N->getOpcode() == ISD::TargetConstantFP; @@ -1236,7 +1240,6 @@ public: // Return the address space this GlobalAddress belongs to. unsigned getAddressSpace() const; - static bool classof(const GlobalAddressSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::GlobalAddress || N->getOpcode() == ISD::TargetGlobalAddress || @@ -1256,7 +1259,6 @@ public: int getIndex() const { return FI; } - static bool classof(const FrameIndexSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::FrameIndex || N->getOpcode() == ISD::TargetFrameIndex; @@ -1276,7 +1278,6 @@ public: int getIndex() const { return JTI; } unsigned char getTargetFlags() const { return TargetFlags; } - static bool classof(const JumpTableSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::JumpTable || N->getOpcode() == ISD::TargetJumpTable; @@ -1337,7 +1338,6 @@ public: Type *getType() const; - static bool classof(const ConstantPoolSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::ConstantPool || N->getOpcode() == ISD::TargetConstantPool; @@ -1361,7 +1361,6 @@ public: int getIndex() const { return Index; } int64_t getOffset() const { return Offset; } - static bool classof(const TargetIndexSDNode*) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::TargetIndex; } @@ -1380,7 +1379,6 @@ public: MachineBasicBlock *getBasicBlock() const { return MBB; } - static bool classof(const BasicBlockSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::BasicBlock; } @@ -1390,7 +1388,7 @@ public: /// BUILD_VECTORs. class BuildVectorSDNode : public SDNode { // These are constructed as SDNodes and then cast to BuildVectorSDNodes. - explicit BuildVectorSDNode(); // Do not implement + explicit BuildVectorSDNode() LLVM_DELETED_FUNCTION; public: /// isConstantSplat - Check if this is a constant splat, and if so, find the /// smallest element size that splats the vector. If MinSplatBits is @@ -1405,7 +1403,6 @@ public: unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits = 0, bool isBigEndian = false); - static inline bool classof(const BuildVectorSDNode *) { return true; } static inline bool classof(const SDNode *N) { return N->getOpcode() == ISD::BUILD_VECTOR; } @@ -1426,7 +1423,6 @@ public: /// getValue - return the contained Value. const Value *getValue() const { return V; } - static bool classof(const SrcValueSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::SRCVALUE; } @@ -1441,7 +1437,6 @@ public: const MDNode *getMD() const { return MD; } - static bool classof(const MDNodeSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MDNODE_SDNODE; } @@ -1458,7 +1453,6 @@ public: unsigned getReg() const { return Reg; } - static bool classof(const RegisterSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::Register; } @@ -1475,7 +1469,6 @@ public: const uint32_t *getRegMask() const { return RegMask; } - static bool classof(const RegisterMaskSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::RegisterMask; } @@ -1483,18 +1476,19 @@ public: class BlockAddressSDNode : public SDNode { const BlockAddress *BA; + int64_t Offset; unsigned char TargetFlags; friend class SelectionDAG; BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, - unsigned char Flags) + int64_t o, unsigned char Flags) : SDNode(NodeTy, DebugLoc(), getSDVTList(VT)), - BA(ba), TargetFlags(Flags) { + BA(ba), Offset(o), TargetFlags(Flags) { } public: const BlockAddress *getBlockAddress() const { return BA; } + int64_t getOffset() const { return Offset; } unsigned char getTargetFlags() const { return TargetFlags; } - static bool classof(const BlockAddressSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::BlockAddress || N->getOpcode() == ISD::TargetBlockAddress; @@ -1512,7 +1506,6 @@ class EHLabelSDNode : public SDNode { public: MCSymbol *getLabel() const { return Label; } - static bool classof(const EHLabelSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::EH_LABEL; } @@ -1532,7 +1525,6 @@ public: const char *getSymbol() const { return Symbol; } unsigned char getTargetFlags() const { return TargetFlags; } - static bool classof(const ExternalSymbolSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::ExternalSymbol || N->getOpcode() == ISD::TargetExternalSymbol; @@ -1550,7 +1542,6 @@ public: ISD::CondCode get() const { return Condition; } - static bool classof(const CondCodeSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::CONDCODE; } @@ -1570,7 +1561,6 @@ class CvtRndSatSDNode : public SDNode { public: ISD::CvtCode getCvtCode() const { return CvtCode; } - static bool classof(const CvtRndSatSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::CONVERT_RNDSAT; } @@ -1589,7 +1579,6 @@ public: EVT getVT() const { return ValueType; } - static bool classof(const VTSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::VALUETYPE; } @@ -1633,7 +1622,6 @@ public: /// isUnindexed - Return true if this is NOT a pre/post inc/dec load/store. bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } - static bool classof(const LSBaseSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::LOAD || N->getOpcode() == ISD::STORE; @@ -1665,7 +1653,6 @@ public: const SDValue &getBasePtr() const { return getOperand(1); } const SDValue &getOffset() const { return getOperand(2); } - static bool classof(const LoadSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::LOAD; } @@ -1696,7 +1683,6 @@ public: const SDValue &getBasePtr() const { return getOperand(2); } const SDValue &getOffset() const { return getOperand(3); } - static bool classof(const StoreSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::STORE; } @@ -1737,7 +1723,6 @@ public: MemRefsEnd = NewMemRefsEnd; } - static bool classof(const MachineSDNode *) { return true; } static bool classof(const SDNode *N) { return N->isMachineOpcode(); } diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index c52599b..b46d153 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -19,13 +19,14 @@ #ifndef LLVM_CODEGEN_SLOTINDEXES_H #define LLVM_CODEGEN_SLOTINDEXES_H -#include "llvm/CodeGen/MachineInstrBundle.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/ilist.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ilist.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/Support/Allocator.h" namespace llvm { @@ -631,17 +632,8 @@ namespace llvm { // Specialize IntervalMapInfo for half-open slot index intervals. - template <typename> struct IntervalMapInfo; - template <> struct IntervalMapInfo<SlotIndex> { - static inline bool startLess(const SlotIndex &x, const SlotIndex &a) { - return x < a; - } - static inline bool stopLess(const SlotIndex &b, const SlotIndex &x) { - return b <= x; - } - static inline bool adjacent(const SlotIndex &a, const SlotIndex &b) { - return a == b; - } + template <> + struct IntervalMapInfo<SlotIndex> : IntervalMapHalfOpenInfo<SlotIndex> { }; } diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 9849e92..e7098e4 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -15,9 +15,9 @@ #ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H #define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H +#include "llvm/ADT/StringRef.h" #include "llvm/MC/SectionKind.h" #include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/ADT/StringRef.h" namespace llvm { class MachineModuleInfo; @@ -55,13 +55,12 @@ public: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; - /// getExprForDwarfGlobalReference - Return an MCExpr to use for a reference - /// to the specified global variable from exception handling information. - /// + /// getTTypeGlobalReference - Return an MCExpr to use for a reference to the + /// specified type info global variable from exception handling information. virtual const MCExpr * - getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding, - MCStreamer &Streamer) const; + getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding, + MCStreamer &Streamer) const; // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. virtual MCSymbol * @@ -103,12 +102,12 @@ public: virtual bool shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *) const; - /// getExprForDwarfGlobalReference - The mach-o version of this method + /// getTTypeGlobalReference - The mach-o version of this method /// defaults to returning a stub reference. virtual const MCExpr * - getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding, - MCStreamer &Streamer) const; + getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding, + MCStreamer &Streamer) const; // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. virtual MCSymbol * diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h new file mode 100644 index 0000000..4c4a2a8 --- /dev/null +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -0,0 +1,167 @@ +//===-- llvm/CodeGen/TargetSchedule.h - Sched Machine Model -----*- 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 a wrapper around MCSchedModel that allows the interface to +// benefit from information currently only available in TargetInstrInfo. +// Ideally, the scheduling interface would be fully defined in the MC layer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETSCHEDMODEL_H +#define LLVM_TARGET_TARGETSCHEDMODEL_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCInstrItineraries.h" +#include "llvm/MC/MCSchedule.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +namespace llvm { + +class TargetRegisterInfo; +class TargetSubtargetInfo; +class TargetInstrInfo; +class MachineInstr; + +/// Provide an instruction scheduling machine model to CodeGen passes. +class TargetSchedModel { + // For efficiency, hold a copy of the statically defined MCSchedModel for this + // processor. + MCSchedModel SchedModel; + InstrItineraryData InstrItins; + const TargetSubtargetInfo *STI; + const TargetInstrInfo *TII; + + SmallVector<unsigned, 16> ResourceFactors; + unsigned MicroOpFactor; // Multiply to normalize microops to resource units. + unsigned ResourceLCM; // Resource units per cycle. Latency normalization factor. +public: + TargetSchedModel(): STI(0), TII(0) {} + + /// \brief Initialize the machine model for instruction scheduling. + /// + /// The machine model API keeps a copy of the top-level MCSchedModel table + /// indices and may query TargetSubtargetInfo and TargetInstrInfo to resolve + /// dynamic properties. + void init(const MCSchedModel &sm, const TargetSubtargetInfo *sti, + const TargetInstrInfo *tii); + + /// Return the MCSchedClassDesc for this instruction. + const MCSchedClassDesc *resolveSchedClass(const MachineInstr *MI) const; + + /// \brief TargetInstrInfo getter. + const TargetInstrInfo *getInstrInfo() const { return TII; } + + /// \brief Return true if this machine model includes an instruction-level + /// scheduling model. + /// + /// This is more detailed than the course grain IssueWidth and default + /// latency properties, but separate from the per-cycle itinerary data. + bool hasInstrSchedModel() const; + + const MCSchedModel *getMCSchedModel() const { return &SchedModel; } + + /// \brief Return true if this machine model includes cycle-to-cycle itinerary + /// data. + /// + /// This models scheduling at each stage in the processor pipeline. + bool hasInstrItineraries() const; + + const InstrItineraryData *getInstrItineraries() const { + if (hasInstrItineraries()) + return &InstrItins; + return 0; + } + + /// \brief Identify the processor corresponding to the current subtarget. + unsigned getProcessorID() const { return SchedModel.getProcessorID(); } + + /// \brief Maximum number of micro-ops that may be scheduled per cycle. + unsigned getIssueWidth() const { return SchedModel.IssueWidth; } + + /// \brief Return the number of issue slots required for this MI. + unsigned getNumMicroOps(const MachineInstr *MI, + const MCSchedClassDesc *SC = 0) const; + + /// \brief Get the number of kinds of resources for this target. + unsigned getNumProcResourceKinds() const { + return SchedModel.getNumProcResourceKinds(); + } + + /// \brief Get a processor resource by ID for convenience. + const MCProcResourceDesc *getProcResource(unsigned PIdx) const { + return SchedModel.getProcResource(PIdx); + } + + typedef const MCWriteProcResEntry *ProcResIter; + + // \brief Get an iterator into the processor resources consumed by this + // scheduling class. + ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const { + // The subtarget holds a single resource table for all processors. + return STI->getWriteProcResBegin(SC); + } + ProcResIter getWriteProcResEnd(const MCSchedClassDesc *SC) const { + return STI->getWriteProcResEnd(SC); + } + + /// \brief Multiply the number of units consumed for a resource by this factor + /// to normalize it relative to other resources. + unsigned getResourceFactor(unsigned ResIdx) const { + return ResourceFactors[ResIdx]; + } + + /// \brief Multiply number of micro-ops by this factor to normalize it + /// relative to other resources. + unsigned getMicroOpFactor() const { + return MicroOpFactor; + } + + /// \brief Multiply cycle count by this factor to normalize it relative to + /// other resources. This is the number of resource units per cycle. + unsigned getLatencyFactor() const { + return ResourceLCM; + } + + /// \brief Compute operand latency based on the available machine model. + /// + /// Computes and return the latency of the given data dependent def and use + /// when the operand indices are already known. UseMI may be NULL for an + /// unknown user. + /// + /// FindMin may be set to get the minimum vs. expected latency. Minimum + /// latency is used for scheduling groups, while expected latency is for + /// instruction cost and critical path. + unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, + const MachineInstr *UseMI, unsigned UseOperIdx, + bool FindMin) const; + + /// \brief Compute the instruction latency based on the available machine + /// model. + /// + /// 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; + + /// \brief Output dependency latency of a pair of defs of the same register. + /// + /// This is typically one cycle. + unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *DepMI) const; + +private: + /// getDefLatency is a helper for computeOperandLatency. Return the + /// instruction's latency if operand lookup is not required. + /// Otherwise return -1. + int getDefLatency(const MachineInstr *DefMI, bool FindMin) const; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index eb38cd3..f8a6503 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -33,6 +33,10 @@ namespace llvm { class MVT { public: enum SimpleValueType { + // INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are + // considered extended value types. + INVALID_SIMPLE_VALUE_TYPE = -1, + // If you change this numbering, you must change the values in // ValueTypes.td as well! Other = 0, // This is a non-standard value @@ -56,50 +60,65 @@ namespace llvm { FIRST_FP_VALUETYPE = f16, LAST_FP_VALUETYPE = ppcf128, - v2i8 = 13, // 2 x i8 - v4i8 = 14, // 4 x i8 - v8i8 = 15, // 8 x i8 - v16i8 = 16, // 16 x i8 - v32i8 = 17, // 32 x i8 - v2i16 = 18, // 2 x i16 - v4i16 = 19, // 4 x i16 - v8i16 = 20, // 8 x i16 - v16i16 = 21, // 16 x i16 - v2i32 = 22, // 2 x i32 - v4i32 = 23, // 4 x i32 - v8i32 = 24, // 8 x i32 - v16i32 = 25, // 16 x i32 - v1i64 = 26, // 1 x i64 - v2i64 = 27, // 2 x i64 - v4i64 = 28, // 4 x i64 - v8i64 = 29, // 8 x i64 - v16i64 = 30, // 16 x i64 - - v2f16 = 31, // 2 x f16 - v2f32 = 32, // 2 x f32 - v4f32 = 33, // 4 x f32 - v8f32 = 34, // 8 x f32 - v2f64 = 35, // 2 x f64 - v4f64 = 36, // 4 x f64 - - FIRST_VECTOR_VALUETYPE = v2i8, - LAST_VECTOR_VALUETYPE = v4f64, - FIRST_INTEGER_VECTOR_VALUETYPE = v2i8, + v2i1 = 13, // 2 x i1 + v4i1 = 14, // 4 x i1 + v8i1 = 15, // 8 x i1 + v16i1 = 16, // 16 x i1 + 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 + + 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 + FIRST_FP_VECTOR_VALUETYPE = v2f16, - LAST_FP_VECTOR_VALUETYPE = v4f64, + LAST_FP_VECTOR_VALUETYPE = v8f64, - x86mmx = 37, // This is an X86 MMX value + FIRST_VECTOR_VALUETYPE = v2i1, + LAST_VECTOR_VALUETYPE = v8f64, - Glue = 38, // This glues nodes together during pre-RA sched + x86mmx = 49, // This is an X86 MMX value - isVoid = 39, // This has no value + Glue = 50, // This glues nodes together during pre-RA sched - Untyped = 40, // This value takes a register, but has + isVoid = 51, // This has no value + + Untyped = 52, // This value takes a register, but has // unspecified type. The register class // will be determined by the opcode. - LAST_VALUETYPE = 41, // This always remains at the end of the list. + LAST_VALUETYPE = 53, // 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 @@ -131,14 +150,7 @@ namespace llvm { // iPTR - An int value the size of the pointer of the current // target. This should only be used internal to tblgen! - iPTR = 255, - - // LastSimpleValueType - The greatest valid SimpleValueType value. - LastSimpleValueType = 255, - - // INVALID_SIMPLE_VALUE_TYPE - Simple value types greater than or equal - // to this are considered extended value types. - INVALID_SIMPLE_VALUE_TYPE = LastSimpleValueType + 1 + iPTR = 255 }; SimpleValueType SimpleTy; @@ -175,6 +187,18 @@ namespace llvm { SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); } + /// is16BitVector - Return true if this is a 16-bit vector type. + bool is16BitVector() const { + return (SimpleTy == MVT::v2i8 || SimpleTy == MVT::v1i16 || + SimpleTy == MVT::v16i1); + } + + /// is32BitVector - Return true if this is a 32-bit vector type. + bool is32BitVector() const { + return (SimpleTy == MVT::v4i8 || SimpleTy == MVT::v2i16 || + SimpleTy == MVT::v1i32); + } + /// is64BitVector - Return true if this is a 64-bit vector type. bool is64BitVector() const { return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || @@ -198,7 +222,9 @@ namespace llvm { /// is512BitVector - Return true if this is a 512-bit vector type. bool is512BitVector() const { - return (SimpleTy == MVT::v8i64 || SimpleTy == MVT::v16i32); + return (SimpleTy == MVT::v8f64 || SimpleTy == MVT::v16f32 || + SimpleTy == MVT::v64i8 || SimpleTy == MVT::v32i16 || + SimpleTy == MVT::v8i64 || SimpleTy == MVT::v16i32); } /// is1024BitVector - Return true if this is a 1024-bit vector type. @@ -233,15 +259,25 @@ namespace llvm { switch (SimpleTy) { default: llvm_unreachable("Not a vector MVT!"); + case v2i1 : + case v4i1 : + case v8i1 : + case v16i1 : + case v32i1 : + case v64i1: return i1; case v2i8 : case v4i8 : case v8i8 : case v16i8: - case v32i8: return i8; + case v32i8: + case v64i8: return i8; + case v1i16: case v2i16: case v4i16: case v8i16: - case v16i16: return i16; + case v16i16: + case v32i16: return i16; + case v1i32: case v2i32: case v4i32: case v8i32: @@ -254,9 +290,11 @@ namespace llvm { case v2f16: return f16; case v2f32: case v4f32: - case v8f32: return f32; + case v8f32: + case v16f32: return f32; case v2f64: - case v4f64: return f64; + case v4f64: + case v8f64: return f64; } } @@ -264,22 +302,32 @@ namespace llvm { switch (SimpleTy) { default: llvm_unreachable("Not a vector MVT!"); - case v32i8: return 32; + case v32i1: + case v32i8: + case v32i16: return 32; + case v64i1: + case v64i8: return 64; + case v16i1: case v16i8: case v16i16: case v16i32: - case v16i64:return 16; + case v16i64: + case v16f32: return 16; + case v8i1 : case v8i8 : case v8i16: case v8i32: case v8i64: - case v8f32: return 8; + case v8f32: + case v8f64: return 8; + case v4i1: case v4i8: case v4i16: case v4i32: case v4i64: case v4f32: case v4f64: return 4; + case v2i1: case v2i8: case v2i16: case v2i32: @@ -287,6 +335,8 @@ namespace llvm { case v2f16: case v2f32: case v2f64: return 2; + case v1i16: + case v1i32: case v1i64: return 1; } } @@ -298,22 +348,33 @@ namespace llvm { case iPTRAny: case iAny: case fAny: + case vAny: llvm_unreachable("Value type is overloaded."); + case Metadata: + llvm_unreachable("Value type is metadata."); default: llvm_unreachable("getSizeInBits called on extended MVT."); case i1 : return 1; - case i8 : return 8; + case v2i1: return 2; + case v4i1: return 4; + case i8 : + case v8i1: return 8; case i16 : case f16: - case v2i8: return 16; + case v16i1: + case v2i8: + case v1i16: return 16; case f32 : case i32 : + case v32i1: case v4i8: case v2i16: - case v2f16: return 32; + case v2f16: + case v1i32: return 32; case x86mmx: case f64 : case i64 : + case v64i1: case v8i8: case v4i16: case v2i32: @@ -335,8 +396,12 @@ namespace llvm { case v4i64: case v8f32: case v4f64: return 256; + case v64i8: + case v32i16: case v16i32: - case v8i64: return 512; + case v8i64: + case v16f32: + case v8f64: return 512; case v16i64:return 1024; } } @@ -353,6 +418,27 @@ namespace llvm { return getStoreSize() * 8; } + /// Return true if this has more bits than VT. + bool bitsGT(MVT VT) const { + return getSizeInBits() > VT.getSizeInBits(); + } + + /// Return true if this has no less bits than VT. + bool bitsGE(MVT VT) const { + return getSizeInBits() >= VT.getSizeInBits(); + } + + /// Return true if this has less bits than VT. + bool bitsLT(MVT VT) const { + return getSizeInBits() < VT.getSizeInBits(); + } + + /// Return true if this has no more bits than VT. + bool bitsLE(MVT VT) const { + return getSizeInBits() <= VT.getSizeInBits(); + } + + static MVT getFloatingPointVT(unsigned BitWidth) { switch (BitWidth) { default: @@ -393,20 +479,32 @@ namespace llvm { switch (VT.SimpleTy) { default: break; + case MVT::i1: + if (NumElements == 2) return MVT::v2i1; + if (NumElements == 4) return MVT::v4i1; + if (NumElements == 8) return MVT::v8i1; + if (NumElements == 16) return MVT::v16i1; + if (NumElements == 32) return MVT::v32i1; + if (NumElements == 64) return MVT::v64i1; + break; case MVT::i8: if (NumElements == 2) return MVT::v2i8; if (NumElements == 4) return MVT::v4i8; if (NumElements == 8) return MVT::v8i8; if (NumElements == 16) return MVT::v16i8; if (NumElements == 32) return MVT::v32i8; + if (NumElements == 64) return MVT::v64i8; break; case MVT::i16: + if (NumElements == 1) return MVT::v1i16; if (NumElements == 2) return MVT::v2i16; if (NumElements == 4) return MVT::v4i16; if (NumElements == 8) return MVT::v8i16; if (NumElements == 16) return MVT::v16i16; + if (NumElements == 32) return MVT::v32i16; break; case MVT::i32: + if (NumElements == 1) return MVT::v1i32; if (NumElements == 2) return MVT::v2i32; if (NumElements == 4) return MVT::v4i32; if (NumElements == 8) return MVT::v8i32; @@ -426,14 +524,22 @@ namespace llvm { 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 == 2) return MVT::v2f64; if (NumElements == 4) return MVT::v4f64; + if (NumElements == 8) return MVT::v8f64; break; } return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); } + + /// Return the value type corresponding to the specified type. This returns + /// all pointers as iPTR. If HandleUnknown is true, unknown types are + /// returned as Other, otherwise they are invalid. + static MVT getVT(Type *Ty, bool HandleUnknown = false); + }; @@ -457,7 +563,7 @@ namespace llvm { bool operator!=(EVT VT) const { if (V.SimpleTy != VT.V.SimpleTy) return true; - if (V.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + if (V.SimpleTy < 0) return LLVMTy != VT.LLVMTy; return false; } @@ -473,7 +579,7 @@ namespace llvm { /// number of bits. static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth) { MVT M = MVT::getIntegerVT(BitWidth); - if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE) + if (M.SimpleTy >= 0) return M; return getExtendedIntegerVT(Context, BitWidth); } @@ -482,7 +588,7 @@ namespace llvm { /// length, where each element is of type VT. static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements) { MVT M = MVT::getVectorVT(VT.V, NumElements); - if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE) + if (M.SimpleTy >= 0) return M; return getExtendedVectorVT(Context, VT, NumElements); } @@ -497,7 +603,7 @@ namespace llvm { unsigned BitWidth = EltTy.getSizeInBits(); MVT IntTy = MVT::getIntegerVT(BitWidth); MVT VecTy = MVT::getVectorVT(IntTy, getVectorNumElements()); - assert(VecTy != MVT::INVALID_SIMPLE_VALUE_TYPE && + assert(VecTy.SimpleTy >= 0 && "Simple vector VT not representable by simple integer vector VT!"); return VecTy; } @@ -505,7 +611,7 @@ namespace llvm { /// isSimple - Test if the given EVT is simple (as opposed to being /// extended). bool isSimple() const { - return V.SimpleTy <= MVT::LastSimpleValueType; + return V.SimpleTy >= 0; } /// isExtended - Test if the given EVT is extended (as opposed to @@ -529,6 +635,16 @@ namespace llvm { return isSimple() ? V.isVector() : isExtendedVector(); } + /// is16BitVector - Return true if this is a 16-bit vector type. + bool is16BitVector() const { + return isSimple() ? V.is16BitVector() : isExtended16BitVector(); + } + + /// is32BitVector - Return true if this is a 32-bit vector type. + bool is32BitVector() const { + return isSimple() ? V.is32BitVector() : isExtended32BitVector(); + } + /// is64BitVector - Return true if this is a 64-bit vector type. bool is64BitVector() const { return isSimple() ? V.is64BitVector() : isExtended64BitVector(); @@ -740,6 +856,8 @@ namespace llvm { bool isExtendedFloatingPoint() const; bool isExtendedInteger() const; bool isExtendedVector() const; + bool isExtended16BitVector() const; + bool isExtended32BitVector() const; bool isExtended64BitVector() const; bool isExtended128BitVector() const; bool isExtended256BitVector() const; diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index f4b75bd..76df6ac 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -33,37 +33,49 @@ def f80 : ValueType<80 , 10>; // 80-bit floating point value def f128 : ValueType<128, 11>; // 128-bit floating point value def ppcf128: ValueType<128, 12>; // PPC 128-bit floating point value -def v2i8 : ValueType<16 , 13>; // 2 x i8 vector value -def v4i8 : ValueType<32 , 14>; // 4 x i8 vector value -def v8i8 : ValueType<64 , 15>; // 8 x i8 vector value -def v16i8 : ValueType<128, 16>; // 16 x i8 vector value -def v32i8 : ValueType<256, 17>; // 32 x i8 vector value -def v2i16 : ValueType<32 , 18>; // 2 x i16 vector value -def v4i16 : ValueType<64 , 19>; // 4 x i16 vector value -def v8i16 : ValueType<128, 20>; // 8 x i16 vector value -def v16i16 : ValueType<256, 21>; // 16 x i16 vector value -def v2i32 : ValueType<64 , 22>; // 2 x i32 vector value -def v4i32 : ValueType<128, 23>; // 4 x i32 vector value -def v8i32 : ValueType<256, 24>; // 8 x i32 vector value -def v16i32 : ValueType<512, 25>; // 16 x i32 vector value -def v1i64 : ValueType<64 , 26>; // 1 x i64 vector value -def v2i64 : ValueType<128, 27>; // 2 x i64 vector value -def v4i64 : ValueType<256, 28>; // 4 x i64 vector value -def v8i64 : ValueType<512, 29>; // 8 x i64 vector value -def v16i64 : ValueType<1024,30>; // 16 x i64 vector value +def v2i1 : ValueType<2 , 13>; // 2 x i1 vector value +def v4i1 : ValueType<4 , 14>; // 4 x i1 vector value +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<256, 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<256, 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 v2f16 : ValueType<32 , 31>; // 2 x f16 vector value -def v2f32 : ValueType<64 , 32>; // 2 x f32 vector value -def v4f32 : ValueType<128, 33>; // 4 x f32 vector value -def v8f32 : ValueType<256, 34>; // 8 x f32 vector value -def v2f64 : ValueType<128, 35>; // 2 x f64 vector value -def v4f64 : ValueType<256, 36>; // 4 x f64 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 x86mmx : ValueType<64 , 37>; // X86 MMX value -def FlagVT : ValueType<0 , 38>; // Pre-RA sched glue -def isVoid : ValueType<0 , 39>; // Produces no value -def untyped: ValueType<8 , 40>; // Produces an untyped 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 MetadataVT: ValueType<0, 250>; // Metadata // Pseudo valuetype mapped to the current pointer size to any address space. diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h new file mode 100644 index 0000000..3bc6ebd --- /dev/null +++ b/include/llvm/CodeGen/VirtRegMap.h @@ -0,0 +1,190 @@ +//===-- llvm/CodeGen/VirtRegMap.h - Virtual Register Map -*- 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 virtual register map. This maps virtual registers to +// physical registers and virtual registers to stack slots. It is created and +// updated by a register allocator and then used by a machine code rewriter that +// adds spill code and rewrites virtual into physical register references. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_VIRTREGMAP_H +#define LLVM_CODEGEN_VIRTREGMAP_H + +#include "llvm/ADT/IndexedMap.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class MachineInstr; + class MachineFunction; + class MachineRegisterInfo; + class TargetInstrInfo; + class raw_ostream; + class SlotIndexes; + + class VirtRegMap : public MachineFunctionPass { + public: + enum { + NO_PHYS_REG = 0, + NO_STACK_SLOT = (1L << 30)-1, + MAX_STACK_SLOT = (1L << 18)-1 + }; + + private: + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineFunction *MF; + + /// Virt2PhysMap - This is a virtual to physical register + /// mapping. Each virtual register is required to have an entry in + /// it; even spilled virtual registers (the register mapped to a + /// spilled register is the temporary used to load it from the + /// stack). + IndexedMap<unsigned, VirtReg2IndexFunctor> Virt2PhysMap; + + /// Virt2StackSlotMap - This is virtual register to stack slot + /// mapping. Each spilled virtual register has an entry in it + /// which corresponds to the stack slot this register is spilled + /// at. + IndexedMap<int, VirtReg2IndexFunctor> Virt2StackSlotMap; + + /// Virt2SplitMap - This is virtual register to splitted virtual register + /// mapping. + IndexedMap<unsigned, VirtReg2IndexFunctor> Virt2SplitMap; + + /// createSpillSlot - Allocate a spill slot for RC from MFI. + unsigned createSpillSlot(const TargetRegisterClass *RC); + + VirtRegMap(const VirtRegMap&) LLVM_DELETED_FUNCTION; + void operator=(const VirtRegMap&) LLVM_DELETED_FUNCTION; + + public: + static char ID; + VirtRegMap() : MachineFunctionPass(ID), Virt2PhysMap(NO_PHYS_REG), + Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) { } + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + MachineFunction &getMachineFunction() const { + assert(MF && "getMachineFunction called before runOnMachineFunction"); + return *MF; + } + + MachineRegisterInfo &getRegInfo() const { return *MRI; } + const TargetRegisterInfo &getTargetRegInfo() const { return *TRI; } + + void grow(); + + /// @brief returns true if the specified virtual register is + /// mapped to a physical register + bool hasPhys(unsigned virtReg) const { + return getPhys(virtReg) != NO_PHYS_REG; + } + + /// @brief returns the physical register mapped to the specified + /// virtual register + unsigned getPhys(unsigned virtReg) const { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + return Virt2PhysMap[virtReg]; + } + + /// @brief creates a mapping for the specified virtual register to + /// the specified physical register + void assignVirt2Phys(unsigned virtReg, unsigned physReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg) && + TargetRegisterInfo::isPhysicalRegister(physReg)); + assert(Virt2PhysMap[virtReg] == NO_PHYS_REG && + "attempt to assign physical register to already mapped " + "virtual register"); + Virt2PhysMap[virtReg] = physReg; + } + + /// @brief clears the specified virtual register's, physical + /// register mapping + void clearVirt(unsigned virtReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2PhysMap[virtReg] != NO_PHYS_REG && + "attempt to clear a not assigned virtual register"); + Virt2PhysMap[virtReg] = NO_PHYS_REG; + } + + /// @brief clears all virtual to physical register mappings + void clearAllVirt() { + Virt2PhysMap.clear(); + grow(); + } + + /// @brief returns true if VirtReg is assigned to its preferred physreg. + bool hasPreferredPhys(unsigned VirtReg); + + /// @brief returns true if VirtReg has a known preferred register. + /// This returns false if VirtReg has a preference that is a virtual + /// register that hasn't been assigned yet. + bool hasKnownPreference(unsigned VirtReg); + + /// @brief records virtReg is a split live interval from SReg. + void setIsSplitFromReg(unsigned virtReg, unsigned SReg) { + Virt2SplitMap[virtReg] = SReg; + } + + /// @brief returns the live interval virtReg is split from. + unsigned getPreSplitReg(unsigned virtReg) const { + return Virt2SplitMap[virtReg]; + } + + /// getOriginal - Return the original virtual register that VirtReg descends + /// from through splitting. + /// A register that was not created by splitting is its own original. + /// This operation is idempotent. + unsigned getOriginal(unsigned VirtReg) const { + unsigned Orig = getPreSplitReg(VirtReg); + return Orig ? Orig : VirtReg; + } + + /// @brief returns true if the specified virtual register is not + /// mapped to a stack slot or rematerialized. + bool isAssignedReg(unsigned virtReg) const { + if (getStackSlot(virtReg) == NO_STACK_SLOT) + return true; + // Split register can be assigned a physical register as well as a + // stack slot or remat id. + return (Virt2SplitMap[virtReg] && Virt2PhysMap[virtReg] != NO_PHYS_REG); + } + + /// @brief returns the stack slot mapped to the specified virtual + /// register + int getStackSlot(unsigned virtReg) const { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + return Virt2StackSlotMap[virtReg]; + } + + /// @brief create a mapping for the specifed virtual register to + /// the next available stack slot + int assignVirt2StackSlot(unsigned virtReg); + /// @brief create a mapping for the specified virtual register to + /// the specified stack slot + void assignVirt2StackSlot(unsigned virtReg, int frameIndex); + + void print(raw_ostream &OS, const Module* M = 0) const; + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const VirtRegMap &VRM) { + VRM.print(OS); + return OS; + } +} // End llvm namespace + +#endif diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index eb20b64..ff765cc 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -1,6 +1,4 @@ -/************************************** -** Created by Kevin from config.h.in ** -***************************************/ +/* include/llvm/Config/config.h.cmake corresponding to config.h.in. */ #ifndef CONFIG_H #define CONFIG_H @@ -8,6 +6,9 @@ /* Bug report URL. */ #define BUG_REPORT_URL "${BUG_REPORT_URL}" +/* Define if we have libxml2 */ +#cmakedefine CLANG_HAVE_LIBXML ${CLANG_HAVE_LIBXML} + /* Relative directory for resource files */ #define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" @@ -17,6 +18,9 @@ /* Default <path> to all compiler invocations for --sysroot=<path>. */ #undef DEFAULT_SYSROOT +/* Define if you want backtraces on crash */ +#cmakedefine ENABLE_BACKTRACES + /* Define if position independent code is enabled */ #cmakedefine ENABLE_PIC diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 5a60ba5..a4f8af4 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -18,6 +18,9 @@ /* Default <path> to all compiler invocations for --sysroot=<path>. */ #undef DEFAULT_SYSROOT +/* Define if you want backtraces on crash */ +#undef ENABLE_BACKTRACES + /* Define if position independent code is enabled */ #undef ENABLE_PIC diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 3944292..fbc3040 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -112,6 +112,12 @@ /* Installation prefix directory */ #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" +/* Define if we have the Intel JIT API runtime support library */ +#cmakedefine LLVM_USE_INTEL_JITEVENTS 1 + +/* Define if we have the oprofile JIT-support library */ +#cmakedefine LLVM_USE_OPROFILE 1 + /* Major version of the LLVM API */ #cmakedefine LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index 9489dfe..af3a324 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -112,6 +112,12 @@ /* Installation prefix directory */ #undef LLVM_PREFIX +/* Define if we have the Intel JIT API runtime support library */ +#undef LLVM_USE_INTEL_JITEVENTS + +/* Define if we have the oprofile JIT-support library */ +#undef LLVM_USE_OPROFILE + /* Major version of the LLVM API */ #undef LLVM_VERSION_MAJOR diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index dd4ea96..0a59cdd 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -15,9 +15,9 @@ #ifndef LLVM_ANALYSIS_DIBUILDER_H #define LLVM_ANALYSIS_DIBUILDER_H -#include "llvm/Support/DataTypes.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class BasicBlock; @@ -63,8 +63,8 @@ namespace llvm { SmallVector<Value *, 4> AllSubprograms; SmallVector<Value *, 4> AllGVs; - DIBuilder(const DIBuilder &); // DO NOT IMPLEMENT - void operator=(const DIBuilder &); // DO NOT IMPLEMENT + DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; + void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; public: explicit DIBuilder(Module &M); @@ -126,6 +126,11 @@ namespace llvm { uint64_t AlignInBits = 0, StringRef Name = StringRef()); + /// \brief Create debugging information entry for a pointer to member. + /// @param PointeeTy Type pointed to by this pointer. + /// @param Class Type for which this pointer points to members of. + DIType createMemberPointerType(DIType PointeeTy, DIType Class); + /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. DIType createReferenceType(unsigned Tag, DIType RTy); @@ -331,12 +336,10 @@ namespace llvm { /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param Elements Enumeration elements. - /// @param Flags Flags (e.g. forward decl) DIType createEnumerationType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, - DIArray Elements, DIType ClassType, - unsigned Flags); + DIArray Elements, DIType ClassType); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -347,13 +350,18 @@ namespace llvm { /// createArtificialType - Create a new DIType with "artificial" flag set. DIType createArtificialType(DIType Ty); + /// createObjectPointerType - Create a new DIType with the "object pointer" + /// flag set. + DIType createObjectPointerType(DIType Ty); + /// createTemporaryType - Create a temporary forward-declared type. DIType createTemporaryType(); DIType createTemporaryType(DIFile F); /// createForwardDecl - Create a temporary forward-declared type. DIType createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, - DIFile F, unsigned Line, unsigned RuntimeLang = 0); + DIFile F, unsigned Line, unsigned RuntimeLang = 0, + uint64_t SizeInBits = 0, uint64_t AlignInBits = 0); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. @@ -368,7 +376,7 @@ namespace llvm { /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. - DISubrange getOrCreateSubrange(int64_t Lo, int64_t Hi); + DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count); /// createGlobalVariable - Create a new descriptor for the specified global. /// @param Name Name of the variable. diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h index 618220f..cc1c6a0 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -17,8 +17,8 @@ #ifndef LLVM_ANALYSIS_DEBUGINFO_H #define LLVM_ANALYSIS_DEBUGINFO_H -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Dwarf.h" @@ -60,7 +60,9 @@ namespace llvm { FlagArtificial = 1 << 6, FlagExplicit = 1 << 7, FlagPrototyped = 1 << 8, - FlagObjcClassComplete = 1 << 9 + FlagObjcClassComplete = 1 << 9, + FlagObjectPointer = 1 << 10, + FlagVector = 1 << 11 }; protected: const MDNode *DbgNode; @@ -70,6 +72,7 @@ namespace llvm { return (unsigned)getUInt64Field(Elt); } uint64_t getUInt64Field(unsigned Elt) const; + int64_t getInt64Field(unsigned Elt) const; DIDescriptor getDescriptorField(unsigned Elt) const; template <typename DescTy> @@ -80,6 +83,7 @@ namespace llvm { GlobalVariable *getGlobalVariableField(unsigned Elt) const; Constant *getConstantField(unsigned Elt) const; Function *getFunctionField(unsigned Elt) const; + void replaceFunctionField(unsigned Elt, Function *F); public: explicit DIDescriptor() : DbgNode(0) {} @@ -139,8 +143,8 @@ namespace llvm { public: explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} - uint64_t getLo() const { return getUInt64Field(1); } - uint64_t getHi() const { return getUInt64Field(2); } + int64_t getLo() const { return getInt64Field(1); } + int64_t getCount() const { return getInt64Field(2); } }; /// DIArray - This descriptor holds an array of descriptors. @@ -213,9 +217,9 @@ namespace llvm { } StringRef getFilename() const { return getStringField(1); } StringRef getDirectory() const { return getStringField(2); } - DICompileUnit getCompileUnit() const{ + DICompileUnit getCompileUnit() const{ assert (getVersion() <= LLVMDebugVersion10 && "Invalid CompileUnit!"); - return getFieldAs<DICompileUnit>(3); + return getFieldAs<DICompileUnit>(3); } }; @@ -250,11 +254,11 @@ namespace llvm { DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } - DICompileUnit getCompileUnit() const{ + DICompileUnit getCompileUnit() const{ assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs<DICompileUnit>(3); - + return getFieldAs<DIFile>(3).getCompileUnit(); } DIFile getFile() const { return getFieldAs<DIFile>(3); } @@ -287,19 +291,25 @@ namespace llvm { 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 isValid() const { return DbgNode && (isBasicType() || isDerivedType() || isCompositeType()); } - StringRef getDirectory() const { + StringRef getDirectory() const { if (getVersion() == llvm::LLVMDebugVersion7) return getCompileUnit().getDirectory(); return getFieldAs<DIFile>(3).getDirectory(); } - StringRef getFilename() const { + StringRef getFilename() const { if (getVersion() == llvm::LLVMDebugVersion7) return getCompileUnit().getFilename(); @@ -344,14 +354,19 @@ namespace llvm { /// return base type size. uint64_t getOriginalTypeSize() const; - /// getObjCProperty - Return property node, if this ivar is + /// getObjCProperty - Return property node, if this ivar is /// associated with one. MDNode *getObjCProperty() const; - StringRef getObjCPropertyName() const { + DIType getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return getFieldAs<DIType>(10); + } + + StringRef getObjCPropertyName() const { if (getVersion() > LLVMDebugVersion11) return StringRef(); - return getStringField(10); + return getStringField(10); } StringRef getObjCPropertyGetterName() const { assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request"); @@ -422,10 +437,10 @@ namespace llvm { DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } DIType getType() const { return getFieldAs<DIType>(3); } - StringRef getFilename() const { + StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); } - StringRef getDirectory() const { + StringRef getDirectory() const { return getFieldAs<DIFile>(4).getDirectory(); } unsigned getLineNumber() const { return getUnsignedField(5); } @@ -441,10 +456,10 @@ namespace llvm { StringRef getName() const { return getStringField(2); } DIType getType() const { return getFieldAs<DIType>(3); } uint64_t getValue() const { return getUInt64Field(4); } - StringRef getFilename() const { + StringRef getFilename() const { return getFieldAs<DIFile>(5).getFilename(); } - StringRef getDirectory() const { + StringRef getDirectory() const { return getFieldAs<DIFile>(5).getDirectory(); } unsigned getLineNumber() const { return getUnsignedField(6); } @@ -462,12 +477,12 @@ namespace llvm { StringRef getName() const { return getStringField(3); } StringRef getDisplayName() const { return getStringField(4); } StringRef getLinkageName() const { return getStringField(5); } - DICompileUnit getCompileUnit() const{ + DICompileUnit getCompileUnit() const{ assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs<DICompileUnit>(6); - return getFieldAs<DIFile>(6).getCompileUnit(); + return getFieldAs<DIFile>(6).getCompileUnit(); } unsigned getLineNumber() const { return getUnsignedField(7); } DICompositeType getType() const { return getFieldAs<DICompositeType>(8); } @@ -497,33 +512,33 @@ namespace llvm { return getFieldAs<DICompositeType>(13); } - unsigned isArtificial() const { + unsigned isArtificial() const { if (getVersion() <= llvm::LLVMDebugVersion8) - return getUnsignedField(14); + return getUnsignedField(14); return (getUnsignedField(14) & FlagArtificial) != 0; } /// isPrivate - Return true if this subprogram has "private" /// access specifier. - bool isPrivate() const { + bool isPrivate() const { if (getVersion() <= llvm::LLVMDebugVersion8) return false; return (getUnsignedField(14) & FlagPrivate) != 0; } /// isProtected - Return true if this subprogram has "protected" /// access specifier. - bool isProtected() const { + bool isProtected() const { if (getVersion() <= llvm::LLVMDebugVersion8) return false; return (getUnsignedField(14) & FlagProtected) != 0; } /// isExplicit - Return true if this subprogram is marked as explicit. - bool isExplicit() const { + bool isExplicit() const { if (getVersion() <= llvm::LLVMDebugVersion8) return false; return (getUnsignedField(14) & FlagExplicit) != 0; } /// isPrototyped - Return true if this subprogram is prototyped. - bool isPrototyped() const { + bool isPrototyped() const { if (getVersion() <= llvm::LLVMDebugVersion8) return false; return (getUnsignedField(14) & FlagPrototyped) != 0; @@ -531,18 +546,18 @@ namespace llvm { unsigned isOptimized() const; - StringRef getFilename() const { + StringRef getFilename() const { if (getVersion() == llvm::LLVMDebugVersion7) return getCompileUnit().getFilename(); - return getFieldAs<DIFile>(6).getFilename(); + return getFieldAs<DIFile>(6).getFilename(); } - StringRef getDirectory() const { + StringRef getDirectory() const { if (getVersion() == llvm::LLVMDebugVersion7) return getCompileUnit().getFilename(); - return getFieldAs<DIFile>(6).getDirectory(); + return getFieldAs<DIFile>(6).getDirectory(); } /// getScopeLineNumber - Get the beginning of the scope of the @@ -558,6 +573,7 @@ namespace llvm { bool describes(const Function *F); Function *getFunction() const { return getFunctionField(16); } + void replaceFunction(Function *F) { replaceFunctionField(16, F); } DIArray getTemplateParams() const { return getFieldAs<DIArray>(17); } DISubprogram getFunctionDeclaration() const { return getFieldAs<DISubprogram>(18); @@ -577,25 +593,25 @@ namespace llvm { StringRef getName() const { return getStringField(3); } StringRef getDisplayName() const { return getStringField(4); } StringRef getLinkageName() const { return getStringField(5); } - DICompileUnit getCompileUnit() const{ + DICompileUnit getCompileUnit() const{ assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs<DICompileUnit>(6); - DIFile F = getFieldAs<DIFile>(6); + DIFile F = getFieldAs<DIFile>(6); return F.getCompileUnit(); } StringRef getFilename() const { if (getVersion() <= llvm::LLVMDebugVersion10) return getContext().getFilename(); return getFieldAs<DIFile>(6).getFilename(); - } + } StringRef getDirectory() const { if (getVersion() <= llvm::LLVMDebugVersion10) return getContext().getDirectory(); return getFieldAs<DIFile>(6).getDirectory(); - } + } unsigned getLineNumber() const { return getUnsignedField(7); } DIType getType() const { return getFieldAs<DIType>(8); } @@ -620,30 +636,35 @@ namespace llvm { DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } - DICompileUnit getCompileUnit() const { + DICompileUnit getCompileUnit() const { assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs<DICompileUnit>(3); - DIFile F = getFieldAs<DIFile>(3); + DIFile F = getFieldAs<DIFile>(3); return F.getCompileUnit(); } - unsigned getLineNumber() const { - return (getUnsignedField(4) << 8) >> 8; + DIFile getFile() const { return getFieldAs<DIFile>(3); } + unsigned getLineNumber() const { + return (getUnsignedField(4) << 8) >> 8; } unsigned getArgNumber() const { - unsigned L = getUnsignedField(4); + 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 { + bool isArtificial() const { if (getVersion() <= llvm::LLVMDebugVersion8) return false; return (getUnsignedField(6) & FlagArtificial) != 0; } + bool isObjectPointer() const { + return (getUnsignedField(6) & FlagObjectPointer) != 0; + } + /// getInlinedAt - If this variable is inlined then return inline location. MDNode *getInlinedAt() const; @@ -656,7 +677,7 @@ namespace llvm { } unsigned getNumAddrElements() const; - + uint64_t getAddrElement(unsigned Idx) const { if (getVersion() <= llvm::LLVMDebugVersion8) return getUInt64Field(Idx+6); @@ -716,23 +737,23 @@ namespace llvm { }; /// DINameSpace - A wrapper for a C++ style name space. - class DINameSpace : public DIScope { + class DINameSpace : public DIScope { public: explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } - StringRef getDirectory() const { + StringRef getDirectory() const { return getFieldAs<DIFile>(3).getDirectory(); } - StringRef getFilename() const { + StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); } - DICompileUnit getCompileUnit() const{ + DICompileUnit getCompileUnit() const{ assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs<DICompileUnit>(3); - return getFieldAs<DIFile>(3).getCompileUnit(); + return getFieldAs<DIFile>(3).getCompileUnit(); } unsigned getLineNumber() const { return getUnsignedField(4); } bool Verify() const; @@ -808,7 +829,7 @@ namespace llvm { /// to hold function specific information. NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); - /// getFnSpecificMDNode - Return a NameMDNode, if available, that is + /// getFnSpecificMDNode - Return a NameMDNode, if available, that is /// suitable to hold function specific information. NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); @@ -826,7 +847,7 @@ namespace llvm { public: /// processModule - Process entire module and collect debug info /// anchors. - void processModule(Module &M); + void processModule(const Module &M); private: /// processType - Process DIType. @@ -839,7 +860,7 @@ namespace llvm { void processSubprogram(DISubprogram SP); /// processDeclare - Process DbgDeclareInst. - void processDeclare(DbgDeclareInst *DDI); + void processDeclare(const DbgDeclareInst *DDI); /// processLocation - Process DILocation. void processLocation(DILocation Loc); diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 8d6054a..5ebf4b0 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -15,9 +15,12 @@ #ifndef LLVM_DEBUGINFO_DICONTEXT_H #define LLVM_DEBUGINFO_DICONTEXT_H -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/RelocVisitor.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -89,18 +92,19 @@ public: } }; +// In place of applying the relocations to the data we've read from disk we use +// a separate mapping table to the side and checking that at locations in the +// dwarf where we expect relocated values. This adds a bit of complexity to the +// dwarf parsing/extraction at the benefit of not allocating memory for the +// entire size of the debug info sections. +typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap; + class DIContext { public: virtual ~DIContext(); /// getDWARFContext - get a context for binary DWARF data. - static DIContext *getDWARFContext(bool isLittleEndian, - StringRef infoSection, - StringRef abbrevSection, - StringRef aRangeSection = StringRef(), - StringRef lineSection = StringRef(), - StringRef stringSection = StringRef(), - StringRef rangeSection = StringRef()); + static DIContext *getDWARFContext(object::ObjectFile *); virtual void dump(raw_ostream &OS) = 0; diff --git a/include/llvm/DefaultPasses.h b/include/llvm/DefaultPasses.h deleted file mode 100644 index 929569d..0000000 --- a/include/llvm/DefaultPasses.h +++ /dev/null @@ -1,168 +0,0 @@ -//===- llvm/DefaultPasses.h - Default Pass Support code --------*- 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 infrastructure for registering the standard pass list. -// This defines sets of standard optimizations that plugins can modify and -// front ends can use. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEFAULT_PASS_SUPPORT_H -#define LLVM_DEFAULT_PASS_SUPPORT_H - -#include <llvm/PassSupport.h> - -namespace llvm { - -class PassManagerBase; - -/// Unique identifiers for the default standard passes. The addresses of -/// these symbols are used to uniquely identify passes from the default list. -namespace DefaultStandardPasses { -extern unsigned char AggressiveDCEID; -extern unsigned char ArgumentPromotionID; -extern unsigned char BasicAliasAnalysisID; -extern unsigned char CFGSimplificationID; -extern unsigned char ConstantMergeID; -extern unsigned char CorrelatedValuePropagationID; -extern unsigned char DeadArgEliminationID; -extern unsigned char DeadStoreEliminationID; -extern unsigned char EarlyCSEID; -extern unsigned char FunctionAttrsID; -extern unsigned char FunctionInliningID; -extern unsigned char GVNID; -extern unsigned char GlobalDCEID; -extern unsigned char GlobalOptimizerID; -extern unsigned char GlobalsModRefID; -extern unsigned char IPSCCPID; -extern unsigned char IndVarSimplifyID; -extern unsigned char InlinerPlaceholderID; -extern unsigned char InstructionCombiningID; -extern unsigned char JumpThreadingID; -extern unsigned char LICMID; -extern unsigned char LoopDeletionID; -extern unsigned char LoopIdiomID; -extern unsigned char LoopRotateID; -extern unsigned char LoopUnrollID; -extern unsigned char LoopUnswitchID; -extern unsigned char MemCpyOptID; -extern unsigned char PruneEHID; -extern unsigned char ReassociateID; -extern unsigned char SCCPID; -extern unsigned char ScalarReplAggregatesID; -extern unsigned char SimplifyLibCallsID; -extern unsigned char StripDeadPrototypesID; -extern unsigned char TailCallEliminationID; -extern unsigned char TypeBasedAliasAnalysisID; -} - -/// StandardPass - The class responsible for maintaining the lists of standard -class StandardPass { - friend class RegisterStandardPassLists; - public: - /// Predefined standard sets of passes - enum StandardSet { - AliasAnalysis, - Function, - Module, - LTO - }; - /// Flags to specify whether a pass should be enabled. Passes registered - /// with the standard sets may specify a minimum optimization level and one - /// or more flags that must be set when constructing the set for the pass to - /// be used. - enum OptimizationFlags { - /// Optimize for size was requested. - OptimizeSize = 1<<0, - /// Allow passes which may make global module changes. - UnitAtATime = 1<<1, - /// UnrollLoops - Allow loop unrolling. - UnrollLoops = 1<<2, - /// Allow library calls to be simplified. - SimplifyLibCalls = 1<<3, - /// Whether the module may have code using exceptions. - HaveExceptions = 1<<4, - // Run an inliner pass as part of this set. - RunInliner = 1<<5 - }; - enum OptimizationFlagComponents { - /// The low bits are used to store the optimization level. When requesting - /// passes, this should store the requested optimisation level. When - /// setting passes, this should set the minimum optimization level at which - /// the pass will run. - OptimizationLevelMask=0xf, - /// The maximum optimisation level at which the pass is run. - MaxOptimizationLevelMask=0xf0, - // Flags that must be set - RequiredFlagMask=0xff00, - // Flags that may not be set. - DisallowedFlagMask=0xff0000, - MaxOptimizationLevelShift=4, - RequiredFlagShift=8, - DisallowedFlagShift=16 - }; - /// Returns the optimisation level from a set of flags. - static unsigned OptimizationLevel(unsigned flags) { - return flags & OptimizationLevelMask; - } - /// Returns the maximum optimization level for this set of flags - static unsigned MaxOptimizationLevel(unsigned flags) { - return (flags & MaxOptimizationLevelMask) >> 4; - } - /// Constructs a set of flags from the specified minimum and maximum - /// optimisation level - static unsigned OptimzationFlags(unsigned minLevel=0, unsigned maxLevel=0xf, - unsigned requiredFlags=0, unsigned disallowedFlags=0) { - return ((minLevel & OptimizationLevelMask) | - ((maxLevel<<MaxOptimizationLevelShift) & MaxOptimizationLevelMask) - | ((requiredFlags<<RequiredFlagShift) & RequiredFlagMask) - | ((disallowedFlags<<DisallowedFlagShift) & DisallowedFlagMask)); - } - /// Returns the flags that must be set for this to match - static unsigned RequiredFlags(unsigned flags) { - return (flags & RequiredFlagMask) >> RequiredFlagShift; - } - /// Returns the flags that must not be set for this to match - static unsigned DisallowedFlags(unsigned flags) { - return (flags & DisallowedFlagMask) >> DisallowedFlagShift; - } - /// Register a standard pass in the specified set. If flags is non-zero, - /// then the pass will only be returned when the specified flags are set. - template<typename passName> - class RegisterStandardPass { - public: - RegisterStandardPass(StandardSet set, unsigned char *runBefore=0, - unsigned flags=0, unsigned char *ID=0) { - // Use the pass's ID if one is not specified - RegisterDefaultPass(PassInfo::NormalCtor_t(callDefaultCtor<passName>), - ID ? ID : (unsigned char*)&passName::ID, runBefore, set, flags); - } - }; - /// Adds the passes from the specified set to the provided pass manager - static void AddPassesFromSet(PassManagerBase *PM, - StandardSet set, - unsigned flags=0, - bool VerifyEach=false, - Pass *inliner=0); - private: - /// Registers the default passes. This is set by RegisterStandardPassLists - /// and is called lazily. - static void (*RegisterDefaultPasses)(void); - /// Creates the verifier pass that is inserted when a VerifyEach is passed to - /// AddPassesFromSet() - static Pass* (*CreateVerifierPass)(void); - /// Registers the pass - static void RegisterDefaultPass(PassInfo::NormalCtor_t constructor, - unsigned char *newPass, - unsigned char *oldPass, - StandardSet set, - unsigned flags=0); -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index ae8b68d..2d60c36 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -15,19 +15,19 @@ #ifndef LLVM_EXECUTION_ENGINE_H #define LLVM_EXECUTION_ENGINE_H -#include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/MC/MCCodeGenInfo.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/ValueHandle.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" -#include <vector> #include <map> #include <string> +#include <vector> namespace llvm { @@ -42,7 +42,7 @@ class JITMemoryManager; class MachineCodeInfo; class Module; class MutexGuard; -class TargetData; +class DataLayout; class Triple; class Type; @@ -88,7 +88,7 @@ public: /// \brief Erase an entry from the mapping table. /// - /// \returns The address that \arg ToUnmap was happed to. + /// \returns The address that \p ToUnmap was happed to. void *RemoveMapping(const MutexGuard &, const GlobalValue *ToUnmap); }; @@ -104,7 +104,7 @@ class ExecutionEngine { ExecutionEngineState EEState; /// The target data for the platform for which execution is being performed. - const TargetData *TD; + const DataLayout *TD; /// Whether lazy JIT compilation is enabled. bool CompilingLazily; @@ -123,7 +123,7 @@ protected: /// optimize for the case where there is only one module. SmallVector<Module*, 1> Modules; - void setTargetData(const TargetData *td) { TD = td; } + void setDataLayout(const DataLayout *td) { TD = td; } /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); @@ -213,7 +213,7 @@ public: //===--------------------------------------------------------------------===// - const TargetData *getTargetData() const { return TD; } + const DataLayout *getDataLayout() const { return TD; } /// removeModule - Remove a Module from the list of modules. Returns true if /// M is found. @@ -244,11 +244,18 @@ public: /// Map the address of a JIT section as returned from the memory manager /// to the address in the target process as the running code will see it. /// This is the address which will be used for relocation resolution. - virtual void mapSectionAddress(void *LocalAddress, uint64_t TargetAddress) { + virtual void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) { llvm_unreachable("Re-mapping of section addresses not supported with this " "EE!"); } + // finalizeObject - This method should be called after sections within an + // object have been relocated using mapSectionAddress. When this method is + // called the MCJIT execution engine will reapply relocations for a loaded + // object. This method has no effect for the legacy JIT engine or the + // interpeter. + virtual void finalizeObject() {} + /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a program. /// diff --git a/include/llvm/ExecutionEngine/IntelJITEventsWrapper.h b/include/llvm/ExecutionEngine/IntelJITEventsWrapper.h deleted file mode 100644 index ca87342..0000000 --- a/include/llvm/ExecutionEngine/IntelJITEventsWrapper.h +++ /dev/null @@ -1,102 +0,0 @@ -//===-- IntelJITEventsWrapper.h - Intel JIT Events API Wrapper --*- 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 a wrapper for the Intel JIT Events API. It allows for the -// implementation of the jitprofiling library to be swapped with an alternative -// implementation (for testing). To include this file, you must have the -// jitprofiling.h header available; it is available in Intel(R) VTune(TM) -// Amplifier XE 2011. -// -//===----------------------------------------------------------------------===// - -#ifndef INTEL_JIT_EVENTS_WRAPPER_H -#define INTEL_JIT_EVENTS_WRAPPER_H - -#include <jitprofiling.h> - -namespace llvm { - -class IntelJITEventsWrapper { - // Function pointer types for testing implementation of Intel jitprofiling - // library - typedef int (*NotifyEventPtr)(iJIT_JVM_EVENT, void*); - typedef void (*RegisterCallbackExPtr)(void *, iJIT_ModeChangedEx ); - typedef iJIT_IsProfilingActiveFlags (*IsProfilingActivePtr)(void); - typedef void (*FinalizeThreadPtr)(void); - typedef void (*FinalizeProcessPtr)(void); - typedef unsigned int (*GetNewMethodIDPtr)(void); - - NotifyEventPtr NotifyEventFunc; - RegisterCallbackExPtr RegisterCallbackExFunc; - IsProfilingActivePtr IsProfilingActiveFunc; - FinalizeThreadPtr FinalizeThreadFunc; - FinalizeProcessPtr FinalizeProcessFunc; - GetNewMethodIDPtr GetNewMethodIDFunc; - -public: - bool isAmplifierRunning() { - return iJIT_IsProfilingActive() == iJIT_SAMPLING_ON; - } - - IntelJITEventsWrapper() - : NotifyEventFunc(::iJIT_NotifyEvent), - RegisterCallbackExFunc(::iJIT_RegisterCallbackEx), - IsProfilingActiveFunc(::iJIT_IsProfilingActive), - FinalizeThreadFunc(::FinalizeThread), - FinalizeProcessFunc(::FinalizeProcess), - GetNewMethodIDFunc(::iJIT_GetNewMethodID) { - } - - IntelJITEventsWrapper(NotifyEventPtr NotifyEventImpl, - RegisterCallbackExPtr RegisterCallbackExImpl, - IsProfilingActivePtr IsProfilingActiveImpl, - FinalizeThreadPtr FinalizeThreadImpl, - FinalizeProcessPtr FinalizeProcessImpl, - GetNewMethodIDPtr GetNewMethodIDImpl) - : NotifyEventFunc(NotifyEventImpl), - RegisterCallbackExFunc(RegisterCallbackExImpl), - IsProfilingActiveFunc(IsProfilingActiveImpl), - FinalizeThreadFunc(FinalizeThreadImpl), - FinalizeProcessFunc(FinalizeProcessImpl), - GetNewMethodIDFunc(GetNewMethodIDImpl) { - } - - // Sends an event anncouncing that a function has been emitted - // return values are event-specific. See Intel documentation for details. - int iJIT_NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { - if (!NotifyEventFunc) - return -1; - return NotifyEventFunc(EventType, EventSpecificData); - } - - // Registers a callback function to receive notice of profiling state changes - void iJIT_RegisterCallbackEx(void *UserData, - iJIT_ModeChangedEx NewModeCallBackFuncEx) { - if (RegisterCallbackExFunc) - RegisterCallbackExFunc(UserData, NewModeCallBackFuncEx); - } - - // Returns the current profiler mode - iJIT_IsProfilingActiveFlags iJIT_IsProfilingActive(void) { - if (!IsProfilingActiveFunc) - return iJIT_NOTHING_RUNNING; - return IsProfilingActiveFunc(); - } - - // Generates a locally unique method ID for use in code registration - unsigned int iJIT_GetNewMethodID(void) { - if (!GetNewMethodIDFunc) - return -1; - return GetNewMethodIDFunc(); - } -}; - -} //namespace llvm - -#endif //INTEL_JIT_EVENTS_WRAPPER_H diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index eea603f..3aa014e 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,10 +15,9 @@ #ifndef LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H #define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H -#include "llvm/Config/config.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" - #include <vector> namespace llvm { @@ -26,6 +25,7 @@ class Function; class MachineFunction; class OProfileWrapper; class IntelJITEventsWrapper; +class ObjectImage; /// JITEvent_EmittedFunctionDetails - Helper struct for containing information /// about a generated machine code function. @@ -76,6 +76,20 @@ public: /// matching NotifyFreeingMachineCode call. virtual void NotifyFreeingMachineCode(void *) {} + /// NotifyObjectEmitted - Called after an object has been successfully + /// emitted to memory. NotifyFunctionEmitted will not be called for + /// individual functions in the object. + /// + /// ELF-specific information + /// The ObjectImage contains the generated object image + /// with section headers updated to reflect the address at which sections + /// were loaded and with relocations performed in-place on debug sections. + virtual void NotifyObjectEmitted(const ObjectImage &Obj) {} + + /// NotifyFreeingObject - Called just before the memory associated with + /// a previously emitted object is released. + virtual void NotifyFreeingObject(const ObjectImage &Obj) {} + #if LLVM_USE_INTEL_JITEVENTS // Construct an IntelJITEventListener static JITEventListener *createIntelJITEventListener(); diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h index 4c75b6a..29e01aa 100644 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -10,6 +10,7 @@ #ifndef LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H #define LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Support/DataTypes.h" #include <string> @@ -22,7 +23,7 @@ namespace llvm { /// memory for the code generated by the JIT. This can be reimplemented by /// clients that have a strong desire to control how the layout of JIT'd memory /// works. -class JITMemoryManager { +class JITMemoryManager : public RTDyldMemoryManager { protected: bool HasGOT; @@ -47,17 +48,6 @@ public: /// debugging, and may be turned on by default in debug mode. virtual void setPoisonMemory(bool poison) = 0; - /// getPointerToNamedFunction - This method returns the address of the - /// specified function. As such it is only useful for resolving library - /// symbols, not code generated symbols. - /// - /// If AbortOnFailure is false and no function with the given name is - /// found, this function silently returns a null pointer. Otherwise, - /// it prints a message to stderr and aborts. - /// - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) = 0; - //===--------------------------------------------------------------------===// // Global Offset Table Management //===--------------------------------------------------------------------===// @@ -112,22 +102,6 @@ public: virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, uint8_t *FunctionEnd) = 0; - /// allocateCodeSection - Allocate a memory block of (at least) the given - /// size suitable for executable code. The SectionID is a unique identifier - /// assigned by the JIT and passed through to the memory manager for - /// the instance class to use if it needs to communicate to the JIT about - /// a given section after the fact. - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) = 0; - - /// allocateDataSection - Allocate a memory block of (at least) the given - /// size suitable for data. The SectionID is a unique identifier - /// assigned by the JIT and passed through to the memory manager for - /// the instance class to use if it needs to communicate to the JIT about - /// a given section after the fact. - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) = 0; - /// allocateSpace - Allocate a memory block of the given size. This method /// cannot be called between calls to startFunctionBody and endFunctionBody. virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; diff --git a/include/llvm/ExecutionEngine/OProfileWrapper.h b/include/llvm/ExecutionEngine/OProfileWrapper.h index ab7f25e..99553a3 100644 --- a/include/llvm/ExecutionEngine/OProfileWrapper.h +++ b/include/llvm/ExecutionEngine/OProfileWrapper.h @@ -41,10 +41,10 @@ class OProfileWrapper { typedef int (*op_unload_native_code_ptr_t)(op_agent_t, uint64_t); // Also used for op_minor_version function which has the same signature - typedef int (*op_major_version_ptr_t)(void); + typedef int (*op_major_version_ptr_t)(); // This is not a part of the opagent API, but is useful nonetheless - typedef bool (*IsOProfileRunningPtrT)(void); + typedef bool (*IsOProfileRunningPtrT)(); op_agent_t Agent; @@ -99,8 +99,8 @@ public: size_t num_entries, struct debug_line_info const* info); int op_unload_native_code(uint64_t addr); - int op_major_version(void); - int op_minor_version(void); + int op_major_version(); + int op_minor_version(); // Returns true if the oprofiled process is running, the opagent library is // loaded and a connection to the agent has been established, and false diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h new file mode 100644 index 0000000..96a48b2 --- /dev/null +++ b/include/llvm/ExecutionEngine/ObjectBuffer.h @@ -0,0 +1,80 @@ +//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a wrapper class to hold the memory into which an +// object will be generated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H +#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// ObjectBuffer - This class acts as a container for the memory buffer used during +/// generation and loading of executable objects using MCJIT and RuntimeDyld. The +/// underlying memory for the object will be owned by the ObjectBuffer instance +/// throughout its lifetime. The getMemBuffer() method provides a way to create a +/// MemoryBuffer wrapper object instance to be owned by other classes (such as +/// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the +/// actual memory it points to. +class ObjectBuffer { +public: + ObjectBuffer() {} + ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {} + virtual ~ObjectBuffer() {} + + /// getMemBuffer - Like MemoryBuffer::getMemBuffer() this function + /// returns a pointer to an object that is owned by the caller. However, + /// the caller does not take ownership of the underlying memory. + MemoryBuffer *getMemBuffer() const { + return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), "", false); + } + + const char *getBufferStart() const { return Buffer->getBufferStart(); } + size_t getBufferSize() const { return Buffer->getBufferSize(); } + +protected: + // The memory contained in an ObjectBuffer + OwningPtr<MemoryBuffer> Buffer; +}; + +/// ObjectBufferStream - This class encapsulates the SmallVector and +/// raw_svector_ostream needed to generate an object using MC code emission +/// while providing a common ObjectBuffer interface for access to the +/// memory once the object has been generated. +class ObjectBufferStream : public ObjectBuffer { +public: + ObjectBufferStream() : OS(SV) {} + virtual ~ObjectBufferStream() {} + + raw_ostream &getOStream() { return OS; } + void flush() + { + OS.flush(); + + // Make the data accessible via the ObjectBuffer::Buffer + Buffer.reset(MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()), + "", + false)); + } + +protected: + SmallVector<char, 4096> SV; // Working buffer into which we JIT. + raw_svector_ostream OS; // streaming wrapper +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h new file mode 100644 index 0000000..d09e4de --- /dev/null +++ b/include/llvm/ExecutionEngine/ObjectImage.h @@ -0,0 +1,61 @@ +//===---- ObjectImage.h - Format independent executuable object image -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a file format independent ObjectImage class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_OBJECTIMAGE_H +#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H + +#include "llvm/ExecutionEngine/ObjectBuffer.h" +#include "llvm/Object/ObjectFile.h" + +namespace llvm { + + +/// ObjectImage - A container class that represents an ObjectFile that has been +/// or is in the process of being loaded into memory for execution. +class ObjectImage { + ObjectImage() LLVM_DELETED_FUNCTION; + ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; + +protected: + OwningPtr<ObjectBuffer> Buffer; + +public: + ObjectImage(ObjectBuffer *Input) : Buffer(Input) {} + virtual ~ObjectImage() {} + + virtual object::symbol_iterator begin_symbols() const = 0; + virtual object::symbol_iterator end_symbols() const = 0; + + virtual object::section_iterator begin_sections() const = 0; + virtual object::section_iterator end_sections() const = 0; + + virtual /* Triple::ArchType */ unsigned getArch() const = 0; + + // Subclasses can override these methods to update the image with loaded + // addresses for sections and common symbols + virtual void updateSectionAddress(const object::SectionRef &Sec, + uint64_t Addr) = 0; + virtual void updateSymbolAddress(const object::SymbolRef &Sym, + uint64_t Addr) = 0; + + virtual StringRef getData() const = 0; + + // Subclasses can override these methods to provide JIT debugging support + virtual void registerWithDebugger() = 0; + virtual void deregisterWithDebugger() = 0; +}; + +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H + diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 9e5ad2f..e2905e3 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -15,43 +15,62 @@ #define LLVM_RUNTIME_DYLD_H #include "llvm/ADT/StringRef.h" +#include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/Support/Memory.h" namespace llvm { class RuntimeDyldImpl; -class MemoryBuffer; +class ObjectImage; // RuntimeDyld clients often want to handle the memory management of -// what gets placed where. For JIT clients, this is an abstraction layer -// over the JITMemoryManager, which references objects by their source -// representations in LLVM IR. +// what gets placed where. For JIT clients, this is the subset of +// JITMemoryManager required for dynamic loading of binaries. +// // FIXME: As the RuntimeDyld fills out, additional routines will be needed // for the varying types of objects to be allocated. class RTDyldMemoryManager { - RTDyldMemoryManager(const RTDyldMemoryManager&); // DO NOT IMPLEMENT - void operator=(const RTDyldMemoryManager&); // DO NOT IMPLEMENT + RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; public: RTDyldMemoryManager() {} virtual ~RTDyldMemoryManager(); - /// allocateCodeSection - Allocate a memory block of (at least) the given - /// size suitable for executable code. + /// Allocate a memory block of (at least) the given size suitable for + /// 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; - /// allocateDataSection - Allocate a memory block of (at least) the given - /// size suitable for data. + /// 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) = 0; - + unsigned SectionID, bool IsReadOnly) = 0; + + /// This method returns the address of the specified function. As such it is + /// only useful for resolving library symbols, not code generated symbols. + /// + /// If AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) = 0; + + /// 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 + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. + /// + /// Returns true if an error occurred, false otherwise. + virtual bool applyPermissions(std::string *ErrMsg = 0) = 0; }; class RuntimeDyld { - RuntimeDyld(const RuntimeDyld &); // DO NOT IMPLEMENT - void operator=(const RuntimeDyld &); // DO NOT IMPLEMENT + RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; + void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public // interface. @@ -62,11 +81,14 @@ protected: // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: - RuntimeDyld(RTDyldMemoryManager*); + RuntimeDyld(RTDyldMemoryManager *); ~RuntimeDyld(); - /// Load an in-memory object file into the dynamic linker. - bool loadObject(MemoryBuffer *InputBuffer); + /// Prepare the object contained in the input buffer for execution. + /// Ownership of the input buffer is transferred to the ObjectImage + /// instance returned from this function if successful. In the case of load + /// failure, the input buffer will be deleted. + ObjectImage *loadObject(ObjectBuffer *InputBuffer); /// Get the address of our local copy of the symbol. This may or may not /// be the address used for relocation (clients can copy the data around @@ -80,11 +102,11 @@ public: /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); - /// mapSectionAddress - map a section to its target address space value. + /// Map a section to its target address space value. /// Map the address of a JIT section as returned from the memory manager /// to the address in the target process as the running code will see it. /// This is the address which will be used for relocation resolution. - void mapSectionAddress(void *LocalAddress, uint64_t TargetAddress); + void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); StringRef getErrorString(); }; diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h new file mode 100644 index 0000000..ba4ba8d0 --- /dev/null +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -0,0 +1,176 @@ +//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of a section-based memory manager used by +// the MCJIT execution engine and RuntimeDyld. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H +#define LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Memory.h" + +namespace llvm { + +/// This is a simple memory manager which implements the methods called by +/// the RuntimeDyld class to allocate memory for section-based loading of +/// objects, usually those generated by the MCJIT execution engine. +/// +/// This memory manager allocates all section memory as read-write. The +/// RuntimeDyld will copy JITed section memory into these allocated blocks +/// and perform any necessary linking and relocations. +/// +/// Any client using this memory manager MUST ensure that section-specific +/// page permissions have been applied before attempting to execute functions +/// in the JITed object. Permissions can be applied either by calling +/// MCJIT::finalizeObject or by calling SectionMemoryManager::applyPermissions +/// directly. Clients of MCJIT should call MCJIT::finalizeObject. +class SectionMemoryManager : public JITMemoryManager { + SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + SectionMemoryManager() { } + virtual ~SectionMemoryManager(); + + /// \brief Allocates a memory block of (at least) the given size suitable for + /// executable code. + /// + /// 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); + + /// \brief Allocates a memory block of (at least) the given size suitable for + /// executable code. + /// + /// 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 *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + bool isReadOnly); + + /// \brief Applies section-specific memory permissions. + /// + /// 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 + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. + /// + /// \returns true if an error occurred, false otherwise. + virtual bool applyPermissions(std::string *ErrMsg = 0); + + /// This method returns the address of the specified function. As such it is + /// only useful for resolving library symbols, not code generated symbols. + /// + /// 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. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); + + /// \brief Invalidate instruction cache for code sections. + /// + /// Some platforms with separate data cache and instruction cache require + /// explicit cache flush, otherwise JIT code manipulations (like resolved + /// relocations) will get to the data cache but not to the instruction cache. + /// + /// This method is not called by RuntimeDyld or MCJIT during the load + /// process. Clients may call this function when needed. See the lli + /// tool for example use. + virtual void invalidateInstructionCache(); + +private: + struct MemoryGroup { + SmallVector<sys::MemoryBlock, 16> AllocatedMem; + SmallVector<sys::MemoryBlock, 16> FreeMem; + sys::MemoryBlock Near; + }; + + uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size, + unsigned Alignment); + + error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, + unsigned Permissions); + + MemoryGroup CodeMem; + MemoryGroup RWDataMem; + MemoryGroup RODataMem; + +public: + /// + /// Functions below are not used by MCJIT or RuntimeDyld, but must be + /// implemented because they are declared as pure virtuals in the base class. + /// + + virtual void setMemoryWritable() { + llvm_unreachable("Unexpected call!"); + } + virtual void setMemoryExecutable() { + llvm_unreachable("Unexpected call!"); + } + virtual void setPoisonMemory(bool poison) { + llvm_unreachable("Unexpected call!"); + } + virtual void AllocateGOT() { + llvm_unreachable("Unexpected call!"); + } + virtual uint8_t *getGOTBase() const { + llvm_unreachable("Unexpected call!"); + return 0; + } + virtual uint8_t *startFunctionBody(const Function *F, + uintptr_t &ActualSize){ + llvm_unreachable("Unexpected call!"); + return 0; + } + virtual uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, + unsigned Alignment) { + llvm_unreachable("Unexpected call!"); + return 0; + } + virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + llvm_unreachable("Unexpected call!"); + } + virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { + llvm_unreachable("Unexpected call!"); + return 0; + } + virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { + llvm_unreachable("Unexpected call!"); + return 0; + } + virtual void deallocateFunctionBody(void *Body) { + llvm_unreachable("Unexpected call!"); + } + virtual uint8_t *startExceptionTable(const Function *F, + uintptr_t &ActualSize) { + llvm_unreachable("Unexpected call!"); + return 0; + } + virtual void endExceptionTable(const Function *F, uint8_t *TableStart, + uint8_t *TableEnd, uint8_t *FrameRegister) { + llvm_unreachable("Unexpected call!"); + } + virtual void deallocateExceptionTable(void *ET) { + llvm_unreachable("Unexpected call!"); + } +}; + +} + +#endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H + diff --git a/include/llvm/Argument.h b/include/llvm/IR/Argument.h index e66075c..f737e40 100644 --- a/include/llvm/Argument.h +++ b/include/llvm/IR/Argument.h @@ -14,10 +14,10 @@ #ifndef LLVM_ARGUMENT_H #define LLVM_ARGUMENT_H -#include "llvm/Value.h" -#include "llvm/Attributes.h" -#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Value.h" namespace llvm { @@ -68,20 +68,19 @@ public: /// attribute on it in its containing function. bool hasNoCaptureAttr() const; - /// hasSRetAttr - Return true if this argument has the sret attribute on it in - /// its containing function. + /// hasStructRetAttr - Return true if this argument has the sret attribute on + /// it in its containing function. bool hasStructRetAttr() const; /// addAttr - Add a Attribute to an argument - void addAttr(Attributes); + void addAttr(Attribute); /// removeAttr - Remove a Attribute from an argument - void removeAttr(Attributes); + void removeAttr(Attribute); /// classof - Methods for support type inquiry through isa, cast, and /// dyn_cast: /// - static inline bool classof(const Argument *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == ArgumentVal; } diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h new file mode 100644 index 0000000..95b654c --- /dev/null +++ b/include/llvm/IR/Attributes.h @@ -0,0 +1,458 @@ +//===-- llvm/Attributes.h - Container for Attributes ------------*- 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 contains the simple types necessary to represent the +/// attributes associated with functions and their calls. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ATTRIBUTES_H +#define LLVM_ATTRIBUTES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <string> + +namespace llvm { + +class AttrBuilder; +class AttributeImpl; +class Constant; +class LLVMContext; +class Type; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief Functions, function parameters, and return types can have attributes +/// to indicate how they should be treated by optimizations and code +/// generation. This class represents one of those attributes. It's light-weight +/// and should be passed around by-value. +class Attribute { +public: + /// This enumeration lists the attributes that can be associated with + /// parameters, function results or the function itself. + /// + /// Note: uwtable is about the ABI or the user mandating an entry in the + /// unwind table. The nounwind attribute is about an exception passing by the + /// function. + /// + /// In a theoretical system that uses tables for profiling and sjlj for + /// exceptions, they would be fully independent. In a normal system that uses + /// tables for both, the semantics are: + /// + /// nil = Needs an entry because an exception might pass by. + /// nounwind = No need for an entry + /// uwtable = Needs an entry because the ABI says so and because + /// an exception might pass by. + /// uwtable + nounwind = Needs an entry because the ABI says so. + + enum AttrKind { + // IR-Level Attributes + None, ///< No attributes have been set + AddressSafety, ///< Address safety checking is on. + Alignment, ///< Alignment of parameter (5 bits) + ///< stored as log2 of alignment with +1 bias + ///< 0 means unaligned (different from align(1)) + AlwaysInline, ///< inline=always + ByVal, ///< Pass structure by value + InlineHint, ///< Source said inlining was desirable + InReg, ///< Force argument to be passed in register + MinSize, ///< Function must be optimized for size first + Naked, ///< Naked function + Nest, ///< Nested function static chain + NoAlias, ///< Considered to not alias after call + NoCapture, ///< Function creates no aliases of pointer + NoDuplicate, ///< Call cannot be duplicated + NoImplicitFloat, ///< Disable implicit floating point insts + NoInline, ///< inline=never + NonLazyBind, ///< Function is called early and/or + ///< often, so lazy binding isn't worthwhile + NoRedZone, ///< Disable redzone + NoReturn, ///< Mark the function as not returning + NoUnwind, ///< Function doesn't unwind stack + OptimizeForSize, ///< opt_size + ReadNone, ///< Function does not access memory + ReadOnly, ///< Function only reads from memory + ReturnsTwice, ///< Function can return twice + SExt, ///< Sign extended before/after call + StackAlignment, ///< Alignment of stack for function (3 bits) + ///< stored as log2 of alignment with +1 bias 0 + ///< means unaligned (different from + ///< alignstack=(1)) + StackProtect, ///< Stack protection. + StackProtectReq, ///< Stack protection required. + StructRet, ///< Hidden pointer to structure to return + UWTable, ///< Function must be in a unwind table + ZExt, ///< Zero extended before/after call + + EndAttrKinds, ///< Sentinal value useful for loops + + AttrKindEmptyKey, ///< Empty key value for DenseMapInfo + AttrKindTombstoneKey ///< Tombstone key value for DenseMapInfo + }; +private: + AttributeImpl *pImpl; + Attribute(AttributeImpl *A) : pImpl(A) {} +public: + Attribute() : pImpl(0) {} + + /// \brief Return a uniquified Attribute object. This takes the uniquified + /// value from the Builder and wraps it in the Attribute class. + static Attribute get(LLVMContext &Context, ArrayRef<AttrKind> Vals); + static Attribute get(LLVMContext &Context, AttrBuilder &B); + + /// \brief Return true if the attribute is present. + bool hasAttribute(AttrKind Val) const; + + /// \brief Return true if attributes exist + bool hasAttributes() const; + + /// \brief Returns the alignment field of an attribute as a byte alignment + /// value. + unsigned getAlignment() const; + + /// \brief Set the alignment field of an attribute. + void setAlignment(unsigned Align); + + /// \brief Returns the stack alignment field of an attribute as a byte + /// alignment value. + unsigned getStackAlignment() const; + + /// \brief Set the stack alignment field of an attribute. + void setStackAlignment(unsigned Align); + + /// \brief Equality and non-equality query methods. + bool operator==(AttrKind K) const; + bool operator!=(AttrKind K) const; + + // FIXME: Remove these 'operator' methods. + bool operator==(const Attribute &A) const { + return pImpl == A.pImpl; + } + bool operator!=(const Attribute &A) const { + return pImpl != A.pImpl; + } + + uint64_t getBitMask() const; + + /// \brief Which attributes cannot be applied to a type. + static Attribute typeIncompatible(Type *Ty); + + /// \brief This returns an integer containing an encoding of all the LLVM + /// attributes found in the given attribute bitset. Any change to this + /// encoding is a breaking change to bitcode compatibility. + static uint64_t encodeLLVMAttributesForBitcode(Attribute Attrs); + + /// \brief This returns an attribute bitset containing the LLVM attributes + /// that have been decoded from the given integer. This function must stay in + /// sync with 'encodeLLVMAttributesForBitcode'. + static Attribute decodeLLVMAttributesForBitcode(LLVMContext &C, + uint64_t EncodedAttrs); + + /// \brief The Attribute is converted to a string of equivalent mnemonic. This + /// is, presumably, for writing out the mnemonics for the assembly writer. + std::string getAsString() const; +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief Provide DenseMapInfo for Attribute::AttrKinds. This is used by +/// AttrBuilder. +template<> struct DenseMapInfo<Attribute::AttrKind> { + static inline Attribute::AttrKind getEmptyKey() { + return Attribute::AttrKindEmptyKey; + } + static inline Attribute::AttrKind getTombstoneKey() { + return Attribute::AttrKindTombstoneKey; + } + static unsigned getHashValue(const Attribute::AttrKind &Val) { + return Val * 37U; + } + static bool isEqual(const Attribute::AttrKind &LHS, + const Attribute::AttrKind &RHS) { + return LHS == RHS; + } +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief This is just a pair of values to associate a set of attributes with +/// an index. +struct AttributeWithIndex { + Attribute Attrs; ///< The attributes that are set, or'd together. + Constant *Val; ///< Value attached to attribute, e.g. alignment. + unsigned Index; ///< Index of the parameter for which the attributes apply. + ///< Index 0 is used for return value attributes. + ///< Index ~0U is used for function attributes. + + static AttributeWithIndex get(LLVMContext &C, unsigned Idx, + ArrayRef<Attribute::AttrKind> Attrs) { + return get(Idx, Attribute::get(C, Attrs)); + } + static AttributeWithIndex get(unsigned Idx, Attribute Attrs) { + AttributeWithIndex P; + P.Index = Idx; + P.Attrs = Attrs; + P.Val = 0; + return P; + } + static AttributeWithIndex get(unsigned Idx, Attribute Attrs, Constant *Val) { + AttributeWithIndex P; + P.Index = Idx; + P.Attrs = Attrs; + P.Val = Val; + return P; + } +}; + +//===----------------------------------------------------------------------===// +// AttributeSet Smart Pointer +//===----------------------------------------------------------------------===// + +class AttrBuilder; +class AttributeSetImpl; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief This class manages the ref count for the opaque AttributeSetImpl +/// object and provides accessors for it. +class AttributeSet { +public: + enum AttrIndex { + ReturnIndex = 0U, + FunctionIndex = ~0U + }; +private: + friend class AttrBuilder; + + /// \brief The attributes that we are managing. This can be null to represent + /// the empty attributes list. + AttributeSetImpl *AttrList; + + /// \brief The attributes for the specified index are returned. Attributes + /// for the result are denoted with Idx = 0. + Attribute getAttributes(unsigned Idx) const; + + explicit AttributeSet(AttributeSetImpl *LI) : AttrList(LI) {} +public: + AttributeSet() : AttrList(0) {} + AttributeSet(const AttributeSet &P) : AttrList(P.AttrList) {} + const AttributeSet &operator=(const AttributeSet &RHS); + + //===--------------------------------------------------------------------===// + // Attribute List Construction and Mutation + //===--------------------------------------------------------------------===// + + /// \brief Return an AttributeSet with the specified parameters in it. + static AttributeSet get(LLVMContext &C, ArrayRef<AttributeWithIndex> Attrs); + static AttributeSet get(LLVMContext &C, unsigned Idx, AttrBuilder &B); + + /// \brief Add the specified attribute at the specified index to this + /// attribute list. Since attribute lists are immutable, this returns the new + /// list. + AttributeSet addAttr(LLVMContext &C, unsigned Idx, Attribute Attrs) const; + + /// \brief Remove the specified attribute at the specified index from this + /// attribute list. Since attribute lists are immutable, this returns the new + /// list. + AttributeSet removeAttr(LLVMContext &C, unsigned Idx, Attribute Attrs) const; + + //===--------------------------------------------------------------------===// + // Attribute List Accessors + //===--------------------------------------------------------------------===// + + /// \brief The attributes for the specified index are returned. + Attribute getParamAttributes(unsigned Idx) const { + return getAttributes(Idx); + } + + /// \brief The attributes for the ret value are returned. + Attribute getRetAttributes() const { + return getAttributes(ReturnIndex); + } + + /// \brief The function attributes are returned. + Attribute getFnAttributes() const { + return getAttributes(FunctionIndex); + } + + /// \brief Return the alignment for the specified function parameter. + unsigned getParamAlignment(unsigned Idx) const { + return getAttributes(Idx).getAlignment(); + } + + /// \brief Return true if the attribute exists at the given index. + bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const; + + /// \brief Return true if attribute exists at the given index. + bool hasAttributes(unsigned Index) const; + + /// \brief Get the stack alignment. + unsigned getStackAlignment(unsigned Index) const; + + /// \brief Return the attributes at the index as a string. + std::string getAsString(unsigned Index) const; + + uint64_t getBitMask(unsigned Index) const; + + /// \brief Return true if the specified attribute is set for at least one + /// parameter or for the return value. + bool hasAttrSomewhere(Attribute::AttrKind Attr) const; + + /// operator==/!= - Provide equality predicates. + bool operator==(const AttributeSet &RHS) const { + return AttrList == RHS.AttrList; + } + bool operator!=(const AttributeSet &RHS) const { + return AttrList != RHS.AttrList; + } + + //===--------------------------------------------------------------------===// + // Attribute List Introspection + //===--------------------------------------------------------------------===// + + /// \brief Return a raw pointer that uniquely identifies this attribute list. + void *getRawPointer() const { + return AttrList; + } + + // Attributes are stored as a dense set of slots, where there is one slot for + // each argument that has an attribute. This allows walking over the dense + // set instead of walking the sparse list of attributes. + + /// \brief Return true if there are no attributes. + bool isEmpty() const { + return AttrList == 0; + } + + /// \brief Return the number of slots used in this attribute list. This is + /// the number of arguments that have an attribute set on them (including the + /// function itself). + unsigned getNumSlots() const; + + /// \brief Return the AttributeWithIndex at the specified slot. This holds a + /// index number plus a set of attributes. + const AttributeWithIndex &getSlot(unsigned Slot) const; + + void dump() const; +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief This class is used in conjunction with the Attribute::get method to +/// create an Attribute object. The object itself is uniquified. The Builder's +/// value, however, is not. So this can be used as a quick way to test for +/// equality, presence of attributes, etc. +class AttrBuilder { + DenseSet<Attribute::AttrKind> Attrs; + uint64_t Alignment; + uint64_t StackAlignment; +public: + AttrBuilder() : Alignment(0), StackAlignment(0) {} + explicit AttrBuilder(uint64_t B) : Alignment(0), StackAlignment(0) { + addRawValue(B); + } + AttrBuilder(const Attribute &A) : Alignment(0), StackAlignment(0) { + addAttributes(A); + } + AttrBuilder(AttributeSet AS, unsigned Idx); + + void clear(); + + /// \brief Add an attribute to the builder. + AttrBuilder &addAttribute(Attribute::AttrKind Val); + + /// \brief Remove an attribute from the builder. + AttrBuilder &removeAttribute(Attribute::AttrKind Val); + + /// \brief Add the attributes from A to the builder. + AttrBuilder &addAttributes(const Attribute &A); + + /// \brief Remove the attributes from A from the builder. + AttrBuilder &removeAttributes(const Attribute &A); + + /// \brief Return true if the builder has the specified attribute. + bool contains(Attribute::AttrKind A) const; + + /// \brief Return true if the builder has IR-level attributes. + bool hasAttributes() const; + + /// \brief Return true if the builder has any attribute that's in the + /// specified attribute. + bool hasAttributes(const Attribute &A) const; + + /// \brief Return true if the builder has an alignment attribute. + bool hasAlignmentAttr() const; + + /// \brief Retrieve the alignment attribute, if it exists. + uint64_t getAlignment() const { return Alignment; } + + /// \brief Retrieve the stack alignment attribute, if it exists. + uint64_t getStackAlignment() const { return StackAlignment; } + + /// \brief This turns an int alignment (which must be a power of 2) into the + /// form used internally in Attribute. + AttrBuilder &addAlignmentAttr(unsigned Align); + + /// \brief This turns an int stack alignment (which must be a power of 2) into + /// the form used internally in Attribute. + AttrBuilder &addStackAlignmentAttr(unsigned Align); + + typedef DenseSet<Attribute::AttrKind>::iterator iterator; + typedef DenseSet<Attribute::AttrKind>::const_iterator const_iterator; + + iterator begin() { return Attrs.begin(); } + iterator end() { return Attrs.end(); } + + const_iterator begin() const { return Attrs.begin(); } + const_iterator end() const { return Attrs.end(); } + + /// \brief Add the raw value to the internal representation. + /// + /// N.B. This should be used ONLY for decoding LLVM bitcode! + AttrBuilder &addRawValue(uint64_t Val); + + /// \brief Remove attributes that are used on functions only. + void removeFunctionOnlyAttrs() { + removeAttribute(Attribute::NoReturn) + .removeAttribute(Attribute::NoUnwind) + .removeAttribute(Attribute::ReadNone) + .removeAttribute(Attribute::ReadOnly) + .removeAttribute(Attribute::NoInline) + .removeAttribute(Attribute::AlwaysInline) + .removeAttribute(Attribute::OptimizeForSize) + .removeAttribute(Attribute::StackProtect) + .removeAttribute(Attribute::StackProtectReq) + .removeAttribute(Attribute::NoRedZone) + .removeAttribute(Attribute::NoImplicitFloat) + .removeAttribute(Attribute::Naked) + .removeAttribute(Attribute::InlineHint) + .removeAttribute(Attribute::StackAlignment) + .removeAttribute(Attribute::UWTable) + .removeAttribute(Attribute::NonLazyBind) + .removeAttribute(Attribute::ReturnsTwice) + .removeAttribute(Attribute::AddressSafety) + .removeAttribute(Attribute::MinSize) + .removeAttribute(Attribute::NoDuplicate); + } + + uint64_t getBitMask() const; + + bool operator==(const AttrBuilder &B); + bool operator!=(const AttrBuilder &B) { + return !(*this == B); + } +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/BasicBlock.h b/include/llvm/IR/BasicBlock.h index d2aa167..15f4aa7 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -14,10 +14,10 @@ #ifndef LLVM_BASICBLOCK_H #define LLVM_BASICBLOCK_H -#include "llvm/Instruction.h" -#include "llvm/SymbolTableListTraits.h" -#include "llvm/ADT/ilist.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/SymbolTableListTraits.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -79,8 +79,8 @@ private: void setParent(Function *parent); friend class SymbolTableListTraits<BasicBlock, Function>; - BasicBlock(const BasicBlock &); // Do not implement - void operator=(const BasicBlock &); // Do not implement + BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION; + void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION; /// BasicBlock ctor - If the function parameter is specified, the basic block /// is automatically inserted at either the end of the function (if @@ -93,8 +93,10 @@ public: LLVMContext &getContext() const; /// Instruction iterators... - typedef InstListType::iterator iterator; - typedef InstListType::const_iterator const_iterator; + typedef InstListType::iterator iterator; + typedef InstListType::const_iterator const_iterator; + typedef InstListType::reverse_iterator reverse_iterator; + typedef InstListType::const_reverse_iterator const_reverse_iterator; /// Create - Creates a new BasicBlock. If the Parent parameter is specified, /// the basic block is automatically inserted at either the end of the @@ -191,6 +193,11 @@ public: inline iterator end () { return InstList.end(); } inline const_iterator end () const { return InstList.end(); } + inline reverse_iterator rbegin() { return InstList.rbegin(); } + inline const_reverse_iterator rbegin() const { return InstList.rbegin(); } + inline reverse_iterator rend () { return InstList.rend(); } + inline const_reverse_iterator rend () const { return InstList.rend(); } + inline size_t size() const { return InstList.size(); } inline bool empty() const { return InstList.empty(); } inline const Instruction &front() const { return InstList.front(); } @@ -213,7 +220,6 @@ public: ValueSymbolTable *getValueSymbolTable(); /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BasicBlock *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == Value::BasicBlockVal; } diff --git a/include/llvm/IR/CMakeLists.txt b/include/llvm/IR/CMakeLists.txt new file mode 100644 index 0000000..2d52a89 --- /dev/null +++ b/include/llvm/IR/CMakeLists.txt @@ -0,0 +1,7 @@ +set(LLVM_TARGET_DEFINITIONS Intrinsics.td) + +tablegen(LLVM Intrinsics.gen -gen-intrinsic) + +add_custom_target(intrinsics_gen ALL + DEPENDS ${llvm_builded_incs_dir}/IR/Intrinsics.gen) +set_target_properties(intrinsics_gen PROPERTIES FOLDER "Tablegenning") diff --git a/include/llvm/CallingConv.h b/include/llvm/IR/CallingConv.h index 4c5ee62..699cea3 100644 --- a/include/llvm/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -47,6 +47,10 @@ namespace CallingConv { // GHC - Calling convention used by the Glasgow Haskell Compiler (GHC). GHC = 10, + // HiPE - Calling convention used by the High-Performance Erlang Compiler + // (HiPE). + HiPE = 11, + // Target - This is the start of the target-specific calling conventions, // e.g. fastcall and thiscall on X86. FirstTargetCC = 64, @@ -94,7 +98,29 @@ namespace CallingConv { /// MBLAZE_INTR - Calling convention used for MBlaze interrupt support /// routines (i.e. GCC's save_volatiles attribute). - MBLAZE_SVOL = 74 + MBLAZE_SVOL = 74, + + /// SPIR_FUNC - Calling convention for SPIR non-kernel device functions. + /// No lowering or expansion of arguments. + /// Structures are passed as a pointer to a struct with the byval attribute. + /// Functions can only call SPIR_FUNC and SPIR_KERNEL functions. + /// Functions can only have zero or one return values. + /// Variable arguments are not allowed, except for printf. + /// How arguments/return values are lowered are not specified. + /// Functions are only visible to the devices. + SPIR_FUNC = 75, + + /// SPIR_KERNEL - Calling convention for SPIR kernel functions. + /// Inherits the restrictions of SPIR_FUNC, except + /// Cannot have non-void return values. + /// Cannot have variable arguments. + /// Can also be called by the host. + /// Is externally visible. + SPIR_KERNEL = 76, + + /// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins + Intel_OCL_BI = 77 + }; } // End CallingConv namespace diff --git a/include/llvm/Constant.h b/include/llvm/IR/Constant.h index e0e516d..36a4538 100644 --- a/include/llvm/Constant.h +++ b/include/llvm/IR/Constant.h @@ -14,7 +14,7 @@ #ifndef LLVM_CONSTANT_H #define LLVM_CONSTANT_H -#include "llvm/User.h" +#include "llvm/IR/User.h" namespace llvm { class APInt; @@ -39,8 +39,8 @@ namespace llvm { /// don't have to worry about the lifetime of the objects. /// @brief LLVM Constant Representation class Constant : public User { - void operator=(const Constant &); // Do not implement - Constant(const Constant &); // Do not implement + void operator=(const Constant &) LLVM_DELETED_FUNCTION; + Constant(const Constant &) LLVM_DELETED_FUNCTION; virtual void anchor(); protected: @@ -65,6 +65,9 @@ public: /// true for things like constant expressions that could divide by zero. bool canTrap() const; + /// isThreadDependent - Return true if the value can vary between threads. + bool isThreadDependent() const; + /// isConstantUsed - Return true if the constant has users other than constant /// exprs and other dangling things. bool isConstantUsed() const; @@ -97,7 +100,15 @@ public: /// 'this' is a constant expr. Constant *getAggregateElement(unsigned Elt) const; Constant *getAggregateElement(Constant *Elt) const; - + + /// getSplatValue - If this is a splat vector constant, meaning that all of + /// the elements have the same value, return that value. Otherwise return 0. + Constant *getSplatValue() const; + + /// If C is a constant integer then return its value, otherwise C must be a + /// vector of constant integers, all equal, and the common value is returned. + const APInt &getUniqueInteger() const; + /// destroyConstant - Called if some element of this constant is no longer /// valid. At this point only other constants may be on the use_list for this /// constant. Any constants on our Use list must also be destroy'd. The @@ -108,8 +119,6 @@ public: virtual void destroyConstant() { llvm_unreachable("Not reached!"); } //// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Constant *) { return true; } - static inline bool classof(const GlobalValue *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() >= ConstantFirstVal && V->getValueID() <= ConstantLastVal; diff --git a/include/llvm/Constants.h b/include/llvm/IR/Constants.h index fdd5382..0f49fe5 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/IR/Constants.h @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// // /// @file -/// This file contains the declarations for the subclasses of Constant, +/// This file contains the declarations for the subclasses of Constant, /// which represent the different flavors of constant values that live in LLVM. -/// Note that Constants are immutable (once created they never change) and are +/// Note that Constants are immutable (once created they never change) and are /// fully shared by structural equivalence. This means that two structurally /// equivalent constants will always have the same address. Constant's are /// created on demand as needed and never deleted: thus clients don't have to @@ -21,11 +21,11 @@ #ifndef LLVM_CONSTANTS_H #define LLVM_CONSTANTS_H -#include "llvm/Constant.h" -#include "llvm/OperandTraits.h" -#include "llvm/ADT/APInt.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/OperandTraits.h" namespace llvm { @@ -44,13 +44,13 @@ template<class ConstantClass, class TypeClass> struct ConvertConstantType; //===----------------------------------------------------------------------===// -/// This is the shared class of boolean and integer constants. This class +/// This is the shared class of boolean and integer constants. This class /// represents both boolean and integral constants. /// @brief Class for constant integers. class ConstantInt : public Constant { virtual void anchor(); - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - ConstantInt(const ConstantInt &); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION; ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; protected: @@ -63,11 +63,11 @@ public: static ConstantInt *getFalse(LLVMContext &Context); static Constant *getTrue(Type *Ty); static Constant *getFalse(Type *Ty); - + /// If Ty is a vector type, return a Constant with a splat of the given /// value. Otherwise return a ConstantInt for the given value. static Constant *get(Type *Ty, uint64_t V, bool isSigned = false); - + /// Return a ConstantInt with the specified integer value for the specified /// type. If the type is wider than 64 bits, the value will be zero-extended /// to fit the type, unless isSigned is true, in which case the value will @@ -84,27 +84,27 @@ public: /// @brief Get a ConstantInt for a specific signed value. static ConstantInt *getSigned(IntegerType *Ty, int64_t V); static Constant *getSigned(Type *Ty, int64_t V); - + /// Return a ConstantInt with the specified value and an implied Type. The /// type is the integer type that corresponds to the bit width of the value. static ConstantInt *get(LLVMContext &Context, const APInt &V); /// Return a ConstantInt constructed from the string strStart with the given - /// radix. + /// radix. static ConstantInt *get(IntegerType *Ty, StringRef Str, uint8_t radix); - + /// If Ty is a vector type, return a Constant with a splat of the given /// value. Otherwise return a ConstantInt for the given value. static Constant *get(Type* Ty, const APInt& V); - + /// Return the constant as an APInt value reference. This allows clients to /// obtain a copy of the value, with all its precision in tact. /// @brief Return the constant's value. inline const APInt &getValue() const { return Val; } - + /// getBitWidth - Return the bitwidth of this constant. unsigned getBitWidth() const { return Val.getBitWidth(); } @@ -126,8 +126,8 @@ public: return Val.getSExtValue(); } - /// A helper method that can be used to determine if the constant contained - /// within is equal to a constant. This only works for very small values, + /// A helper method that can be used to determine if the constant contained + /// within is equal to a constant. This only works for very small values, /// because this is all that can be represented with all types. /// @brief Determine if this constant's value is same as an unsigned char. bool equalsInt(uint64_t V) const { @@ -141,11 +141,11 @@ public: return reinterpret_cast<IntegerType*>(Value::getType()); } - /// This static method returns true if the type Ty is big enough to - /// represent the value V. This can be used to avoid having the get method + /// This static method returns true if the type Ty is big enough to + /// represent the value V. This can be used to avoid having the get method /// assert when V is larger than Ty can represent. Note that there are two /// versions of this method, one for unsigned and one for signed integers. - /// Although ConstantInt canonicalizes everything to an unsigned integer, + /// Although ConstantInt canonicalizes everything to an unsigned integer, /// the signed version avoids callers having to convert a signed quantity /// to the appropriate unsigned type before calling the method. /// @returns true if V is a valid value for type Ty @@ -162,7 +162,7 @@ public: return Val == 0; } - /// This is just a convenience method to make client code smaller for a + /// This is just a convenience method to make client code smaller for a /// common case. It also correctly performs the comparison without the /// potential for an assertion from getZExtValue(). /// @brief Determine if the value is one. @@ -174,17 +174,17 @@ public: /// to true. /// @returns true iff this constant's bits are all set to true. /// @brief Determine if the value is all ones. - bool isMinusOne() const { + bool isMinusOne() const { return Val.isAllOnesValue(); } /// This function will return true iff this constant represents the largest /// value that may be represented by the constant's type. - /// @returns true iff this is the largest value that may be represented + /// @returns true iff this is the largest value that may be represented /// by this type. /// @brief Determine if the value is maximal. bool isMaxValue(bool isSigned) const { - if (isSigned) + if (isSigned) return Val.isMaxSignedValue(); else return Val.isMaxValue(); @@ -192,11 +192,11 @@ public: /// This function will return true iff this constant represents the smallest /// value that may be represented by this constant's type. - /// @returns true if this is the smallest value that may be represented by + /// @returns true if this is the smallest value that may be represented by /// this type. /// @brief Determine if the value is minimal. bool isMinValue(bool isSigned) const { - if (isSigned) + if (isSigned) return Val.isMinSignedValue(); else return Val.isMinValue(); @@ -221,7 +221,6 @@ public: } /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const ConstantInt *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantIntVal; } @@ -234,8 +233,8 @@ public: class ConstantFP : public Constant { APFloat Val; virtual void anchor(); - void *operator new(size_t, unsigned);// DO NOT IMPLEMENT - ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION; friend class LLVMContextImpl; protected: ConstantFP(Type *Ty, const APFloat& V); @@ -249,7 +248,7 @@ public: /// method returns the negative zero constant for floating point or vector /// floating point types; for all other types, it returns the null value. static Constant *getZeroValueForNegation(Type *Ty); - + /// get() - This returns a ConstantFP, or a vector containing a splat of a /// ConstantFP, for the specified value in the specified type. This should /// only be used for simple constant values like 2.0/1.0 etc, that are @@ -259,7 +258,7 @@ public: static ConstantFP *get(LLVMContext &Context, const APFloat &V); static ConstantFP *getNegativeZero(Type* Ty); static ConstantFP *getInfinity(Type *Ty, bool Negative = false); - + /// isValueValidForType - return true if Ty is big enough to represent V. static bool isValueValidForType(Type *Ty, const APFloat &V); inline const APFloat &getValueAPF() const { return Val; } @@ -283,15 +282,11 @@ public: bool isExactlyValue(double V) const { bool ignored; - // convert is not supported on this type - if (&Val.getSemantics() == &APFloat::PPCDoubleDouble) - return false; APFloat FV(V); FV.convert(Val.getSemantics(), APFloat::rmNearestTiesToEven, &ignored); return isExactlyValue(FV); } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ConstantFP *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantFPVal; } @@ -301,8 +296,8 @@ public: /// ConstantAggregateZero - All zero aggregate value /// class ConstantAggregateZero : public Constant { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - ConstantAggregateZero(const ConstantAggregateZero &); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION; protected: explicit ConstantAggregateZero(Type *ty) : Constant(ty, ConstantAggregateZeroVal, 0, 0) {} @@ -313,7 +308,7 @@ protected: } public: static ConstantAggregateZero *get(Type *Ty); - + virtual void destroyConstant(); /// getSequentialElement - If this CAZ has array or vector type, return a zero @@ -334,7 +329,6 @@ public: /// Methods for support type inquiry through isa, cast, and dyn_cast: /// - static bool classof(const ConstantAggregateZero *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantAggregateZeroVal; } @@ -346,13 +340,13 @@ public: /// class ConstantArray : public Constant { friend struct ConstantArrayCreator<ConstantArray, ArrayType>; - ConstantArray(const ConstantArray &); // DO NOT IMPLEMENT + ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; protected: ConstantArray(ArrayType *T, ArrayRef<Constant *> Val); public: // ConstantArray accessors static Constant *get(ArrayType *T, ArrayRef<Constant*> V); - + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -367,7 +361,6 @@ public: virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ConstantArray *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantArrayVal; } @@ -385,7 +378,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // class ConstantStruct : public Constant { friend struct ConstantArrayCreator<ConstantStruct, StructType>; - ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT + ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; protected: ConstantStruct(StructType *T, ArrayRef<Constant *> Val); public: @@ -399,7 +392,7 @@ public: static Constant *getAnon(ArrayRef<Constant*> V, bool Packed = false) { return get(getTypeForElements(V, Packed), V); } - static Constant *getAnon(LLVMContext &Ctx, + static Constant *getAnon(LLVMContext &Ctx, ArrayRef<Constant*> V, bool Packed = false) { return get(getTypeForElements(Ctx, V, Packed), V); } @@ -412,7 +405,7 @@ public: static StructType *getTypeForElements(LLVMContext &Ctx, ArrayRef<Constant*> V, bool Packed = false); - + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -426,7 +419,6 @@ public: virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ConstantStruct *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantStructVal; } @@ -445,17 +437,17 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// class ConstantVector : public Constant { friend struct ConstantArrayCreator<ConstantVector, VectorType>; - ConstantVector(const ConstantVector &); // DO NOT IMPLEMENT + ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; protected: ConstantVector(VectorType *T, ArrayRef<Constant *> Val); public: // ConstantVector accessors static Constant *get(ArrayRef<Constant*> V); - + /// getSplat - Return a ConstantVector with the specified constant in each /// element. static Constant *getSplat(unsigned NumElts, Constant *Elt); - + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -474,7 +466,6 @@ public: virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ConstantVector *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantVectorVal; } @@ -491,8 +482,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) /// ConstantPointerNull - a constant pointer value that points to null /// class ConstantPointerNull : public Constant { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - ConstantPointerNull(const ConstantPointerNull &); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION; protected: explicit ConstantPointerNull(PointerType *T) : Constant(reinterpret_cast<Type*>(T), @@ -517,12 +508,11 @@ public: } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ConstantPointerNull *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantPointerNullVal; } }; - + //===----------------------------------------------------------------------===// /// ConstantDataSequential - A vector or array constant whose element type is a /// simple 1/2/4/8-byte integer or float/double, and whose elements are just @@ -537,19 +527,19 @@ class ConstantDataSequential : public Constant { /// DataElements - A pointer to the bytes underlying this constant (which is /// owned by the uniquing StringMap). const char *DataElements; - + /// Next - This forms a link list of ConstantDataSequential nodes that have /// the same value but different type. For example, 0,0,0,1 could be a 4 /// element array of i8, or a 1-element array of i32. They'll both end up in /// the same StringMap bucket, linked up. ConstantDataSequential *Next; - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - ConstantDataSequential(const ConstantDataSequential &); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION; protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, 0, 0), DataElements(Data), Next(0) {} ~ConstantDataSequential() { delete Next; } - + static Constant *getImpl(StringRef Bytes, Type *Ty); protected: @@ -558,13 +548,13 @@ protected: return User::operator new(s, 0); } public: - + /// isElementTypeCompatible - Return true if a ConstantDataSequential can be /// formed with a vector or array of the specified element type. /// ConstantDataArray only works with normal float and int types that are /// stored densely in memory, not with things like i42 or x86_f80. static bool isElementTypeCompatible(const Type *Ty); - + /// getElementAsInteger - If this is a sequential container of integers (of /// any size), return the specified element in the low bits of a uint64_t. uint64_t getElementAsInteger(unsigned i) const; @@ -576,26 +566,26 @@ public: /// getElementAsFloat - If this is an sequential container of floats, return /// the specified element as a float. float getElementAsFloat(unsigned i) const; - + /// getElementAsDouble - If this is an sequential container of doubles, return /// the specified element as a double. double getElementAsDouble(unsigned i) const; - + /// getElementAsConstant - Return a Constant for a specified index's element. /// Note that this has to compute a new constant to return, so it isn't as /// efficient as getElementAsInteger/Float/Double. Constant *getElementAsConstant(unsigned i) const; - + /// getType - Specialize the getType() method to always return a /// SequentialType, which reduces the amount of casting needed in parts of the /// compiler. inline SequentialType *getType() const { return reinterpret_cast<SequentialType*>(Value::getType()); } - + /// getElementType - Return the element type of the array/vector. Type *getElementType() const; - + /// getNumElements - Return the number of elements in the array or vector. unsigned getNumElements() const; @@ -604,14 +594,14 @@ public: /// byte. uint64_t getElementByteSize() const; - + /// isString - This method returns true if this is an array of i8. bool isString() const; - + /// isCString - This method returns true if the array "isString", ends with a /// nul byte, and does not contains any other nul bytes. bool isCString() const; - + /// getAsString - If this array is isString(), then this method returns the /// array as a StringRef. Otherwise, it asserts out. /// @@ -619,7 +609,7 @@ public: assert(isString() && "Not a string"); return getRawDataValues(); } - + /// getAsCString - If this array is isCString(), then this method returns the /// array (without the trailing null byte) as a StringRef. Otherwise, it /// asserts out. @@ -629,17 +619,16 @@ public: StringRef Str = getAsString(); return Str.substr(0, Str.size()-1); } - + /// getRawDataValues - Return the raw, underlying, bytes of this data. Note /// that this is an extremely tricky thing to work with, as it exposes the /// host endianness of the data elements. StringRef getRawDataValues() const; - + virtual void destroyConstant(); - + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// - static bool classof(const ConstantDataSequential *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantDataArrayVal || V->getValueID() == ConstantDataVectorVal; @@ -655,8 +644,8 @@ private: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataArray : public ConstantDataSequential { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - ConstantDataArray(const ConstantDataArray &); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION; virtual void anchor(); friend class ConstantDataSequential; explicit ConstantDataArray(Type *ty, const char *Data) @@ -667,7 +656,7 @@ protected: return User::operator new(s, 0); } public: - + /// get() constructors - Return a constant with array type with an element /// count and element type matching the ArrayRef passed in. Note that this /// can return a ConstantAggregateZero object. @@ -677,7 +666,7 @@ public: static Constant *get(LLVMContext &Context, ArrayRef<uint64_t> Elts); static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); - + /// getString - This method constructs a CDS and initializes it with a text /// string. The default behavior (AddNull==true) causes a null terminator to /// be placed at the end of the array (increasing the length of the string by @@ -692,15 +681,14 @@ public: inline ArrayType *getType() const { return reinterpret_cast<ArrayType*>(Value::getType()); } - + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// - static bool classof(const ConstantDataArray *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantDataArrayVal; } }; - + //===----------------------------------------------------------------------===// /// ConstantDataVector - A vector constant whose element type is a simple /// 1/2/4/8-byte integer or float/double, and whose elements are just simple @@ -708,8 +696,8 @@ public: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataVector : public ConstantDataSequential { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - ConstantDataVector(const ConstantDataVector &); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION; virtual void anchor(); friend class ConstantDataSequential; explicit ConstantDataVector(Type *ty, const char *Data) @@ -720,7 +708,7 @@ protected: return User::operator new(s, 0); } public: - + /// get() constructors - Return a constant with vector type with an element /// count and element type matching the ArrayRef passed in. Note that this /// can return a ConstantAggregateZero object. @@ -730,7 +718,7 @@ public: static Constant *get(LLVMContext &Context, ArrayRef<uint64_t> Elts); static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); - + /// getSplat - Return a ConstantVector with the specified constant in each /// element. The specified constant has to be a of a compatible type (i8/i16/ /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. @@ -739,17 +727,16 @@ public: /// getSplatValue - If this is a splat constant, meaning that all of the /// elements have the same value, return that value. Otherwise return NULL. Constant *getSplatValue() const; - + /// getType - Specialize the getType() method to always return a VectorType, /// which reduces the amount of casting needed in parts of the compiler. /// inline VectorType *getType() const { return reinterpret_cast<VectorType*>(Value::getType()); } - + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// - static bool classof(const ConstantDataVector *) { return true; } static bool classof(const Value *V) { return V->getValueID() == ConstantDataVectorVal; } @@ -760,28 +747,27 @@ public: /// BlockAddress - The address of a basic block. /// class BlockAddress : public Constant { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void *operator new(size_t s) { return User::operator new(s, 2); } BlockAddress(Function *F, BasicBlock *BB); public: /// get - Return a BlockAddress for the specified function and basic block. static BlockAddress *get(Function *F, BasicBlock *BB); - + /// get - Return a BlockAddress for the specified basic block. The basic /// block must be embedded into a function. static BlockAddress *get(BasicBlock *BB); - + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - + Function *getFunction() const { return (Function*)Op<0>().get(); } BasicBlock *getBasicBlock() const { return (BasicBlock*)Op<1>().get(); } - + virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); - + /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BlockAddress *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == BlockAddressVal; } @@ -793,7 +779,7 @@ struct OperandTraits<BlockAddress> : }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value) - + //===----------------------------------------------------------------------===// /// ConstantExpr - a constant value that is initialized with an expression using @@ -823,14 +809,14 @@ public: /// getAlignOf constant expr - computes the alignment of a type in a target /// independent way (Note: the return type is an i64). static Constant *getAlignOf(Type *Ty); - + /// getSizeOf constant expr - computes the (alloc) size of a type (in /// address-units, not bits) in a target independent way (Note: the return /// type is an i64). /// static Constant *getSizeOf(Type *Ty); - /// getOffsetOf constant expr - computes the offset of a struct field in a + /// getOffsetOf constant expr - computes the offset of a struct field in a /// target independent way (Note: the return type is an i64). /// static Constant *getOffsetOf(StructType *STy, unsigned FieldNo); @@ -839,7 +825,7 @@ public: /// which supports any aggregate type, and any Constant index. /// static Constant *getOffsetOf(Type *Ty, Constant *FieldNo); - + static Constant *getNeg(Constant *C, bool HasNUW = false, bool HasNSW =false); static Constant *getFNeg(Constant *C); static Constant *getNot(Constant *C); @@ -945,7 +931,7 @@ public: Type *Ty ///< The type to zext or bitcast C to ); - // @brief Create a SExt or BitCast cast constant expression + // @brief Create a SExt or BitCast cast constant expression static Constant *getSExtOrBitCast( Constant *C, ///< The constant to sext or bitcast Type *Ty ///< The type to sext or bitcast C to @@ -965,14 +951,14 @@ public: /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts static Constant *getIntegerCast( - Constant *C, ///< The integer constant to be casted + Constant *C, ///< The integer constant to be casted Type *Ty, ///< The integer type to cast to bool isSigned ///< Whether C should be treated as signed or not ); /// @brief Create a FPExt, Bitcast or FPTrunc for fp -> fp casts static Constant *getFPCast( - Constant *C, ///< The integer constant to be casted + Constant *C, ///< The integer constant to be casted Type *Ty ///< The integer type to cast to ); @@ -1076,7 +1062,7 @@ public: /// getWithOperandReplaced - Return a constant expression identical to this /// one, but with the specified operand set to the specified value. Constant *getWithOperandReplaced(unsigned OpNo, Constant *Op) const; - + /// getWithOperands - This returns the current constant expression with the /// operands replaced with the specified values. The specified array must /// have the same number of operands as our current one. @@ -1090,15 +1076,23 @@ public: /// current one. Constant *getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const; + /// getAsInstruction - Returns an Instruction which implements the same operation + /// 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 + /// would make it harder to remove ConstantExprs altogether. + Instruction *getAsInstruction(); + virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ConstantExpr *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == ConstantExprVal; } - + private: // Shadow Value::setValueSubclassData with a private forwarding method so that // subclasses cannot accidentally use it. @@ -1125,8 +1119,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) /// LangRef.html#undefvalues for details. /// class UndefValue : public Constant { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - UndefValue(const UndefValue &); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION; protected: explicit UndefValue(Type *T) : Constant(T, UndefValueVal, 0, 0) {} protected: @@ -1143,11 +1137,11 @@ public: /// getSequentialElement - If this Undef has array or vector type, return a /// undef with the right element type. UndefValue *getSequentialElement() const; - + /// getStructElement - If this undef has struct type, return a undef with the /// right element type for the specified element. UndefValue *getStructElement(unsigned Elt) const; - + /// getElementValue - Return an undef of the right value for the specified GEP /// index. UndefValue *getElementValue(Constant *C) const; @@ -1159,7 +1153,6 @@ public: virtual void destroyConstant(); /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const UndefValue *) { return true; } static bool classof(const Value *V) { return V->getValueID() == UndefValueVal; } diff --git a/include/llvm/Target/TargetData.h b/include/llvm/IR/DataLayout.h index 4f94ab7..cc02017 100644 --- a/include/llvm/Target/TargetData.h +++ b/include/llvm/IR/DataLayout.h @@ -1,4 +1,4 @@ -//===-- llvm/Target/TargetData.h - Data size & alignment info ---*- C++ -*-===// +//===--------- llvm/DataLayout.h - Data size & alignment info ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines target properties related to datatype size/offset/alignment +// This file defines layout properties related to datatype size/offset/alignment // information. It uses lazy annotations to cache information about how // structure types are laid out and used. // @@ -17,11 +17,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETDATA_H -#define LLVM_TARGET_TARGETDATA_H +#ifndef LLVM_DATALAYOUT_H +#define LLVM_DATALAYOUT_H -#include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -36,8 +37,9 @@ class LLVMContext; template<typename T> class ArrayRef; -/// Enum used to categorize the alignment types stored by TargetAlignElem +/// Enum used to categorize the alignment types stored by LayoutAlignElem enum AlignTypeEnum { + INVALID_ALIGN = 0, ///< An invalid alignment INTEGER_ALIGN = 'i', ///< Integer type alignment VECTOR_ALIGN = 'v', ///< Vector type alignment FLOAT_ALIGN = 'f', ///< Floating point type alignment @@ -45,38 +47,55 @@ enum AlignTypeEnum { STACK_ALIGN = 's' ///< Stack objects alignment }; -/// Target alignment element. +/// Layout alignment element. +/// +/// Stores the alignment data associated with a given alignment type (integer, +/// vector, float) and type bit width. +/// +/// @note The unusual order of elements in the structure attempts to reduce +/// padding and make the structure slightly more cache friendly. +struct LayoutAlignElem { + unsigned AlignType : 8; ///< Alignment type (AlignTypeEnum) + unsigned TypeBitWidth : 24; ///< Type bit width + unsigned ABIAlign : 16; ///< ABI alignment for this type/bitw + unsigned PrefAlign : 16; ///< Pref. alignment for this type/bitw + + /// Initializer + static LayoutAlignElem get(AlignTypeEnum align_type, unsigned abi_align, + unsigned pref_align, uint32_t bit_width); + /// Equality predicate + bool operator==(const LayoutAlignElem &rhs) const; +}; + +/// Layout pointer alignment element. /// -/// Stores the alignment data associated with a given alignment type (pointer, -/// integer, vector, float) and type bit width. +/// Stores the alignment data associated with a given pointer and address space. /// /// @note The unusual order of elements in the structure attempts to reduce /// padding and make the structure slightly more cache friendly. -struct TargetAlignElem { - AlignTypeEnum AlignType : 8; ///< Alignment type (AlignTypeEnum) +struct PointerAlignElem { unsigned ABIAlign; ///< ABI alignment for this type/bitw unsigned PrefAlign; ///< Pref. alignment for this type/bitw uint32_t TypeBitWidth; ///< Type bit width + uint32_t AddressSpace; ///< Address space for the pointer type /// Initializer - static TargetAlignElem get(AlignTypeEnum align_type, unsigned abi_align, + static PointerAlignElem get(uint32_t addr_space, unsigned abi_align, unsigned pref_align, uint32_t bit_width); /// Equality predicate - bool operator==(const TargetAlignElem &rhs) const; + bool operator==(const PointerAlignElem &rhs) const; }; -/// TargetData - This class holds a parsed version of the target data layout + +/// DataLayout - This class holds a parsed version of the target data layout /// string in a module and provides methods for querying it. The target data /// layout string is specified *by the target* - a frontend generating LLVM IR /// is required to generate the right target data for the target being codegen'd /// to. If some measure of portability is desired, an empty string may be /// specified in the module. -class TargetData : public ImmutablePass { +class DataLayout : public ImmutablePass { private: bool LittleEndian; ///< Defaults to false - unsigned PointerMemSize; ///< Pointer size in bytes - unsigned PointerABIAlign; ///< Pointer ABI alignment - unsigned PointerPrefAlign; ///< Pointer preferred alignment unsigned StackNaturalAlign; ///< Stack natural alignment SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers. @@ -85,13 +104,18 @@ private: /// /// @sa init(). /// @note Could support multiple size pointer alignments, e.g., 32-bit - /// pointers vs. 64-bit pointers by extending TargetAlignment, but for now, + /// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now, /// we don't. - SmallVector<TargetAlignElem, 16> Alignments; + SmallVector<LayoutAlignElem, 16> Alignments; + DenseMap<unsigned, PointerAlignElem> Pointers; /// InvalidAlignmentElem - This member is a signal that a requested alignment /// type and bit width were not found in the SmallVector. - static const TargetAlignElem InvalidAlignmentElem; + static const LayoutAlignElem InvalidAlignmentElem; + + /// InvalidPointerElem - This member is a signal that a requested pointer + /// type and bit width were not found in the DenseSet. + static const PointerAlignElem InvalidPointerElem; // The StructType -> StructLayout map. mutable void *LayoutMap; @@ -101,63 +125,71 @@ private: unsigned pref_align, uint32_t bit_width); unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, bool ABIAlign, Type *Ty) const; + + //! Set/initialize pointer alignments + void setPointerAlignment(uint32_t addr_space, unsigned abi_align, + unsigned pref_align, uint32_t bit_width); + //! Internal helper method that returns requested alignment for type. unsigned getAlignment(Type *Ty, bool abi_or_pref) const; /// Valid alignment predicate. /// - /// Predicate that tests a TargetAlignElem reference returned by get() against + /// Predicate that tests a LayoutAlignElem reference returned by get() against /// InvalidAlignmentElem. - bool validAlignment(const TargetAlignElem &align) const { + bool validAlignment(const LayoutAlignElem &align) const { return &align != &InvalidAlignmentElem; } - /// Initialise a TargetData object with default values, ensure that the - /// target data pass is registered. - void init(); + /// Valid pointer predicate. + /// + /// Predicate that tests a PointerAlignElem reference returned by get() against + /// InvalidPointerElem. + bool validPointer(const PointerAlignElem &align) const { + return &align != &InvalidPointerElem; + } + + /// Parses a target data specification string. Assert if the string is + /// malformed. + void parseSpecifier(StringRef LayoutDescription); public: /// Default ctor. /// /// @note This has to exist, because this is a pass, but it should never be /// used. - TargetData(); + DataLayout(); - /// Constructs a TargetData from a specification string. See init(). - explicit TargetData(StringRef TargetDescription) + /// Constructs a DataLayout from a specification string. See init(). + explicit DataLayout(StringRef LayoutDescription) : ImmutablePass(ID) { - std::string errMsg = parseSpecifier(TargetDescription, this); - assert(errMsg == "" && "Invalid target data layout string."); - (void)errMsg; + init(LayoutDescription); } - /// Parses a target data specification string. Returns an error message - /// if the string is malformed, or the empty string on success. Optionally - /// initialises a TargetData object if passed a non-null pointer. - static std::string parseSpecifier(StringRef TargetDescription, TargetData* td = 0); - /// Initialize target data from properties stored in the module. - explicit TargetData(const Module *M); + explicit DataLayout(const Module *M); - TargetData(const TargetData &TD) : + DataLayout(const DataLayout &TD) : ImmutablePass(ID), LittleEndian(TD.isLittleEndian()), - PointerMemSize(TD.PointerMemSize), - PointerABIAlign(TD.PointerABIAlign), - PointerPrefAlign(TD.PointerPrefAlign), LegalIntWidths(TD.LegalIntWidths), Alignments(TD.Alignments), + Pointers(TD.Pointers), LayoutMap(0) { } - ~TargetData(); // Not virtual, do not subclass this class + ~DataLayout(); // Not virtual, do not subclass this class + + /// Parse a data layout string (with fallback to default values). Ensure that + /// the data layout pass is registered. + void init(StringRef LayoutDescription); - /// Target endianness... + /// Layout endianness... bool isLittleEndian() const { return LittleEndian; } bool isBigEndian() const { return !LittleEndian; } /// getStringRepresentation - Return the string representation of the - /// TargetData. This representation is in the same format accepted by the + /// DataLayout. This representation is in the same format accepted by the /// string constructor above. std::string getStringRepresentation() const; @@ -195,15 +227,42 @@ public: return false; } - /// Target pointer alignment - unsigned getPointerABIAlignment() const { return PointerABIAlign; } + /// Layout pointer alignment + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerABIAlignment(unsigned AS = 0) const { + DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return val->second.ABIAlign; + } /// Return target's alignment for stack-based pointers - unsigned getPointerPrefAlignment() const { return PointerPrefAlign; } - /// Target pointer size - unsigned getPointerSize() const { return PointerMemSize; } - /// Target pointer size, in bits - unsigned getPointerSizeInBits() const { return 8*PointerMemSize; } - + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerPrefAlignment(unsigned AS = 0) const { + DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return val->second.PrefAlign; + } + /// Layout pointer size + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerSize(unsigned AS = 0) const { + DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return val->second.TypeBitWidth; + } + /// Layout pointer size, in bits + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerSizeInBits(unsigned AS = 0) const { + return getPointerSize(AS) * 8; + } /// Size examples: /// /// Type SizeInBits StoreSizeInBits AllocSizeInBits[*] @@ -223,6 +282,7 @@ public: /// getTypeSizeInBits - Return the number of bits necessary to hold the /// specified type. For example, returns 36 for i36 and 80 for x86_fp80. + /// The type passed must have a size (Type::isSized() must return true). uint64_t getTypeSizeInBits(Type* Ty) const; /// getTypeStoreSize - Return the maximum number of bytes that may be @@ -279,10 +339,14 @@ public: /// unsigned getPreferredTypeAlignmentShift(Type *Ty) const; - /// getIntPtrType - Return an unsigned integer type that is the same size or - /// greater to the host pointer size. - /// - IntegerType *getIntPtrType(LLVMContext &C) const; + /// getIntPtrType - Return an integer type with size at least as big as that + /// of a pointer in the given address space. + IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const; + + /// getIntPtrType - Return an integer (vector of integer) type with size at + /// least as big as that of a pointer of the given pointer (vector of pointer) + /// type. + Type *getIntPtrType(Type *) const; /// getIndexedOffset - return the offset from the beginning of the type for /// the specified indices. This is used to implement getelementptr. @@ -318,7 +382,7 @@ public: }; /// StructLayout - used to lazily calculate structure layout information for a -/// target machine, based on the TargetData structure. +/// target machine, based on the DataLayout structure. /// class StructLayout { uint64_t StructSize; @@ -354,8 +418,8 @@ public: } private: - friend class TargetData; // Only TargetData can create this class - StructLayout(StructType *ST, const TargetData &TD); + friend class DataLayout; // Only DataLayout can create this class + StructLayout(StructType *ST, const DataLayout &TD); }; } // End llvm namespace diff --git a/include/llvm/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index da5ad27..5a941520 100644 --- a/include/llvm/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -18,7 +18,8 @@ #ifndef LLVM_DERIVED_TYPES_H #define LLVM_DERIVED_TYPES_H -#include "llvm/Type.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -84,7 +85,6 @@ public: bool isPowerOf2ByteWidth() const; // Methods for support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const IntegerType *) { return true; } static inline bool classof(const Type *T) { return T->getTypeID() == IntegerTyID; } @@ -94,8 +94,8 @@ public: /// FunctionType - Class to represent function types /// class FunctionType : public Type { - FunctionType(const FunctionType &); // Do not implement - const FunctionType &operator=(const FunctionType &); // Do not implement + FunctionType(const FunctionType &) LLVM_DELETED_FUNCTION; + const FunctionType &operator=(const FunctionType &) LLVM_DELETED_FUNCTION; FunctionType(Type *Result, ArrayRef<Type*> Params, bool IsVarArgs); public: @@ -133,7 +133,6 @@ public: unsigned getNumParams() const { return NumContainedTys - 1; } // Methods for support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const FunctionType *) { return true; } static inline bool classof(const Type *T) { return T->getTypeID() == FunctionTyID; } @@ -156,7 +155,6 @@ public: bool indexValid(unsigned Idx) const; // Methods for support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const CompositeType *) { return true; } static inline bool classof(const Type *T) { return T->getTypeID() == ArrayTyID || T->getTypeID() == StructTyID || @@ -183,12 +181,12 @@ public: /// Independent of what kind of struct you have, the body of a struct type are /// laid out in memory consequtively with the elements directly one after the /// other (if the struct is packed) or (if not packed) with padding between the -/// elements as defined by TargetData (which is required to match what the code +/// elements as defined by DataLayout (which is required to match what the code /// generator for a target expects). /// class StructType : public CompositeType { - StructType(const StructType &); // Do not implement - const StructType &operator=(const StructType &); // Do not implement + StructType(const StructType &) LLVM_DELETED_FUNCTION; + const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION; StructType(LLVMContext &C) : CompositeType(C, StructTyID), SymbolTableEntry(0) {} enum { @@ -292,7 +290,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const StructType *) { return true; } static inline bool classof(const Type *T) { return T->getTypeID() == StructTyID; } @@ -308,8 +305,8 @@ public: /// class SequentialType : public CompositeType { Type *ContainedType; ///< Storage for the single contained type. - SequentialType(const SequentialType &); // Do not implement! - const SequentialType &operator=(const SequentialType &); // Do not implement! + SequentialType(const SequentialType &) LLVM_DELETED_FUNCTION; + const SequentialType &operator=(const SequentialType &) LLVM_DELETED_FUNCTION; protected: SequentialType(TypeID TID, Type *ElType) @@ -322,7 +319,6 @@ public: Type *getElementType() const { return ContainedTys[0]; } // Methods for support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const SequentialType *) { return true; } static inline bool classof(const Type *T) { return T->getTypeID() == ArrayTyID || T->getTypeID() == PointerTyID || @@ -336,8 +332,8 @@ public: class ArrayType : public SequentialType { uint64_t NumElements; - ArrayType(const ArrayType &); // Do not implement - const ArrayType &operator=(const ArrayType &); // Do not implement + ArrayType(const ArrayType &) LLVM_DELETED_FUNCTION; + const ArrayType &operator=(const ArrayType &) LLVM_DELETED_FUNCTION; ArrayType(Type *ElType, uint64_t NumEl); public: /// ArrayType::get - This static method is the primary way to construct an @@ -352,7 +348,6 @@ public: uint64_t getNumElements() const { return NumElements; } // Methods for support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const ArrayType *) { return true; } static inline bool classof(const Type *T) { return T->getTypeID() == ArrayTyID; } @@ -363,8 +358,8 @@ public: class VectorType : public SequentialType { unsigned NumElements; - VectorType(const VectorType &); // Do not implement - const VectorType &operator=(const VectorType &); // Do not implement + VectorType(const VectorType &) LLVM_DELETED_FUNCTION; + const VectorType &operator=(const VectorType &) LLVM_DELETED_FUNCTION; VectorType(Type *ElType, unsigned NumEl); public: /// VectorType::get - This static method is the primary way to construct an @@ -419,7 +414,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const VectorType *) { return true; } static inline bool classof(const Type *T) { return T->getTypeID() == VectorTyID; } @@ -429,8 +423,8 @@ public: /// PointerType - Class to represent pointers. /// class PointerType : public SequentialType { - PointerType(const PointerType &); // Do not implement - const PointerType &operator=(const PointerType &); // Do not implement + PointerType(const PointerType &) LLVM_DELETED_FUNCTION; + const PointerType &operator=(const PointerType &) LLVM_DELETED_FUNCTION; explicit PointerType(Type *ElType, unsigned AddrSpace); public: /// PointerType::get - This constructs a pointer to an object of the specified @@ -451,7 +445,6 @@ public: inline unsigned getAddressSpace() const { return getSubclassData(); } // Implement support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const PointerType *) { return true; } static inline bool classof(const Type *T) { return T->getTypeID() == PointerTyID; } diff --git a/include/llvm/Function.h b/include/llvm/IR/Function.h index fdd90d1..1762b2c 100644 --- a/include/llvm/Function.h +++ b/include/llvm/IR/Function.h @@ -18,11 +18,11 @@ #ifndef LLVM_FUNCTION_H #define LLVM_FUNCTION_H -#include "llvm/GlobalValue.h" -#include "llvm/CallingConv.h" -#include "llvm/BasicBlock.h" -#include "llvm/Argument.h" -#include "llvm/Attributes.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -85,11 +85,11 @@ private: BasicBlockListType BasicBlocks; ///< The basic blocks mutable ArgumentListType ArgumentList; ///< The formal arguments ValueSymbolTable *SymTab; ///< Symbol table of args/instructions - AttrListPtr AttributeList; ///< Parameter attributes + AttributeSet AttributeList; ///< Parameter attributes // HasLazyArguments is stored in Value::SubclassData. /*bool HasLazyArguments;*/ - + // The Calling Convention is stored in Value::SubclassData. /*CallingConv::ID CallingConvention;*/ @@ -109,9 +109,9 @@ private: BuildLazyArguments(); } void BuildLazyArguments() const; - - Function(const Function&); // DO NOT IMPLEMENT - void operator=(const Function&); // DO NOT IMPLEMENT + + Function(const Function&) LLVM_DELETED_FUNCTION; + void operator=(const Function&) LLVM_DELETED_FUNCTION; /// Function ctor - If the (optional) Module argument is specified, the /// function is automatically inserted into the end of the function list for @@ -131,7 +131,7 @@ public: Type *getReturnType() const; // Return the type of the ret val FunctionType *getFunctionType() const; // Return the FunctionType for me - /// getContext - Return a pointer to the LLVMContext associated with this + /// getContext - Return a pointer to the LLVMContext associated with this /// function, or NULL if this function is not bound to a context yet. LLVMContext &getContext() const; @@ -147,7 +147,7 @@ public: /// defined in llvm/Intrinsics.h. /// unsigned getIntrinsicID() const LLVM_READONLY; - bool isIntrinsic() const { return getIntrinsicID() != 0; } + bool isIntrinsic() const { return getName().startswith("llvm."); } /// getCallingConv()/setCallingConv(CC) - These method get and set the /// calling convention of this function. The enum values for the known @@ -159,32 +159,26 @@ public: setValueSubclassData((getSubclassDataFromValue() & 1) | (static_cast<unsigned>(CC) << 1)); } - + /// getAttributes - Return the attribute list for this Function. /// - const AttrListPtr &getAttributes() const { return AttributeList; } + const AttributeSet &getAttributes() const { return AttributeList; } /// setAttributes - Set the attribute list for this Function. /// - void setAttributes(const AttrListPtr &attrs) { AttributeList = attrs; } - - /// hasFnAttr - Return true if this function has the given attribute. - bool hasFnAttr(Attributes N) const { - // Function Attributes are stored at ~0 index - return AttributeList.paramHasAttr(~0U, N); - } + void setAttributes(const AttributeSet &attrs) { AttributeList = attrs; } /// addFnAttr - Add function attributes to this function. /// - void addFnAttr(Attributes N) { - // Function Attributes are stored at ~0 index - addAttribute(~0U, N); + void addFnAttr(Attribute::AttrKind N) { + // Function Attribute are stored at ~0 index + addAttribute(AttributeSet::FunctionIndex, Attribute::get(getContext(), N)); } /// removeFnAttr - Remove function attributes from this function. /// - void removeFnAttr(Attributes N) { - // Function Attributes are stored at ~0 index + void removeFnAttr(Attribute N) { + // Function Attribute are stored at ~0 index removeAttribute(~0U, N); } @@ -195,16 +189,11 @@ public: void setGC(const char *Str); void clearGC(); - /// @brief Determine whether the function has the given attribute. - bool paramHasAttr(unsigned i, Attributes attr) const { - return AttributeList.paramHasAttr(i, attr); - } - /// addAttribute - adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attributes attr); - + void addAttribute(unsigned i, Attribute attr); + /// removeAttribute - removes the attribute from the list of attributes. - void removeAttribute(unsigned i, Attributes attr); + void removeAttribute(unsigned i, Attribute attr); /// @brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { @@ -213,50 +202,58 @@ public: /// @brief Determine if the function does not access memory. bool doesNotAccessMemory() const { - return hasFnAttr(Attribute::ReadNone); + return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + Attribute::ReadNone); } - void setDoesNotAccessMemory(bool DoesNotAccessMemory = true) { - if (DoesNotAccessMemory) addFnAttr(Attribute::ReadNone); - else removeFnAttr(Attribute::ReadNone); + void setDoesNotAccessMemory() { + addFnAttr(Attribute::ReadNone); } /// @brief Determine if the function does not access or only reads memory. bool onlyReadsMemory() const { - return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); + return doesNotAccessMemory() || + AttributeList.hasAttribute(AttributeSet::FunctionIndex, + Attribute::ReadOnly); } - void setOnlyReadsMemory(bool OnlyReadsMemory = true) { - if (OnlyReadsMemory) addFnAttr(Attribute::ReadOnly); - else removeFnAttr(Attribute::ReadOnly | Attribute::ReadNone); + void setOnlyReadsMemory() { + addFnAttr(Attribute::ReadOnly); } /// @brief Determine if the function cannot return. bool doesNotReturn() const { - return hasFnAttr(Attribute::NoReturn); + return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + Attribute::NoReturn); } - void setDoesNotReturn(bool DoesNotReturn = true) { - if (DoesNotReturn) addFnAttr(Attribute::NoReturn); - else removeFnAttr(Attribute::NoReturn); + void setDoesNotReturn() { + addFnAttr(Attribute::NoReturn); } /// @brief Determine if the function cannot unwind. bool doesNotThrow() const { - return hasFnAttr(Attribute::NoUnwind); + return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + Attribute::NoUnwind); + } + void setDoesNotThrow() { + addFnAttr(Attribute::NoUnwind); + } + + /// @brief Determine if the call cannot be duplicated. + bool cannotDuplicate() const { + return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + Attribute::NoDuplicate); } - void setDoesNotThrow(bool DoesNotThrow = true) { - if (DoesNotThrow) addFnAttr(Attribute::NoUnwind); - else removeFnAttr(Attribute::NoUnwind); + void setCannotDuplicate() { + addFnAttr(Attribute::NoDuplicate); } /// @brief True if the ABI mandates (or the user requested) that this /// function be in a unwind table. bool hasUWTable() const { - return hasFnAttr(Attribute::UWTable); + return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + Attribute::UWTable); } - void setHasUWTable(bool HasUWTable = true) { - if (HasUWTable) - addFnAttr(Attribute::UWTable); - else - removeFnAttr(Attribute::UWTable); + void setHasUWTable() { + addFnAttr(Attribute::UWTable); } /// @brief True if this function needs an unwind table. @@ -264,30 +261,28 @@ public: return hasUWTable() || !doesNotThrow(); } - /// @brief Determine if the function returns a structure through first + /// @brief Determine if the function returns a structure through first /// pointer argument. bool hasStructRetAttr() const { - return paramHasAttr(1, Attribute::StructRet); + return AttributeList.hasAttribute(1, Attribute::StructRet); } /// @brief Determine if the parameter does not alias other parameters. /// @param n The parameter to check. 1 is the first parameter, 0 is the return bool doesNotAlias(unsigned n) const { - return paramHasAttr(n, Attribute::NoAlias); + return AttributeList.hasAttribute(n, Attribute::NoAlias); } - void setDoesNotAlias(unsigned n, bool DoesNotAlias = true) { - if (DoesNotAlias) addAttribute(n, Attribute::NoAlias); - else removeAttribute(n, Attribute::NoAlias); + void setDoesNotAlias(unsigned n) { + addAttribute(n, Attribute::get(getContext(), Attribute::NoAlias)); } /// @brief Determine if the parameter can be captured. /// @param n The parameter to check. 1 is the first parameter, 0 is the return bool doesNotCapture(unsigned n) const { - return paramHasAttr(n, Attribute::NoCapture); + return AttributeList.hasAttribute(n, Attribute::NoCapture); } - void setDoesNotCapture(unsigned n, bool DoesNotCapture = true) { - if (DoesNotCapture) addAttribute(n, Attribute::NoCapture); - else removeAttribute(n, Attribute::NoCapture); + void setDoesNotCapture(unsigned n) { + addAttribute(n, Attribute::get(getContext(), Attribute::NoCapture)); } /// copyAttributesFrom - copy all additional attributes (those not needed to @@ -400,7 +395,6 @@ public: void viewCFGOnly() const; /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Function *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal; } diff --git a/include/llvm/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 164d976..03c1648 100644 --- a/include/llvm/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -15,10 +15,10 @@ #ifndef LLVM_GLOBAL_ALIAS_H #define LLVM_GLOBAL_ALIAS_H -#include "llvm/GlobalValue.h" -#include "llvm/OperandTraits.h" -#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/OperandTraits.h" namespace llvm { @@ -28,8 +28,8 @@ template<typename ValueSubClass, typename ItemParentClass> class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> { friend class SymbolTableListTraits<GlobalAlias, Module>; - void operator=(const GlobalAlias &); // Do not implement - GlobalAlias(const GlobalAlias &); // Do not implement + void operator=(const GlobalAlias &) LLVM_DELETED_FUNCTION; + GlobalAlias(const GlobalAlias &) LLVM_DELETED_FUNCTION; void setParent(Module *parent); @@ -76,7 +76,6 @@ public: const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const; // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const GlobalAlias *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == Value::GlobalAliasVal; } diff --git a/include/llvm/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 391b830..246e00b 100644 --- a/include/llvm/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -18,7 +18,7 @@ #ifndef LLVM_GLOBALVALUE_H #define LLVM_GLOBALVALUE_H -#include "llvm/Constant.h" +#include "llvm/IR/Constant.h" namespace llvm { @@ -26,7 +26,7 @@ class PointerType; class Module; class GlobalValue : public Constant { - GlobalValue(const GlobalValue &); // do not implement + GlobalValue(const GlobalValue &) LLVM_DELETED_FUNCTION; public: /// @brief An enumeration for the kinds of linkage for global values. enum LinkageTypes { @@ -287,7 +287,6 @@ public: inline const Module *getParent() const { return Parent; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const GlobalValue *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || V->getValueID() == Value::GlobalVariableVal || diff --git a/include/llvm/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 99b7a73..5c42d76 100644 --- a/include/llvm/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -20,10 +20,10 @@ #ifndef LLVM_GLOBAL_VARIABLE_H #define LLVM_GLOBAL_VARIABLE_H -#include "llvm/GlobalValue.h" -#include "llvm/OperandTraits.h" -#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/OperandTraits.h" namespace llvm { @@ -34,9 +34,9 @@ template<typename ValueSubClass, typename ItemParentClass> class GlobalVariable : public GlobalValue, public ilist_node<GlobalVariable> { friend class SymbolTableListTraits<GlobalVariable, Module>; - void *operator new(size_t, unsigned); // Do not implement - void operator=(const GlobalVariable &); // Do not implement - GlobalVariable(const GlobalVariable &); // Do not implement + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION; + GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION; void setParent(Module *parent); @@ -174,7 +174,6 @@ public: virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const GlobalVariable *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == Value::GlobalVariableVal; } diff --git a/include/llvm/IRBuilder.h b/include/llvm/IR/IRBuilder.h index d5b6f47..27f990e 100644 --- a/include/llvm/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -15,12 +15,14 @@ #ifndef LLVM_IRBUILDER_H #define LLVM_IRBUILDER_H -#include "llvm/Instructions.h" -#include "llvm/BasicBlock.h" -#include "llvm/LLVMContext.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Operator.h" #include "llvm/Support/ConstantFolder.h" namespace llvm { @@ -237,7 +239,7 @@ public: return Type::getInt16Ty(Context); } - /// getInt32Ty - Fetch the type resepresenting a 32-bit integer. + /// getInt32Ty - Fetch the type representing a 32-bit integer. IntegerType *getInt32Ty() { return Type::getInt32Ty(Context); } @@ -266,6 +268,10 @@ public: return Type::getInt8PtrTy(Context, AddrSpace); } + IntegerType* getIntPtrTy(DataLayout *DL, unsigned AddrSpace = 0) { + return DL->getIntPtrType(Context, AddrSpace); + } + //===--------------------------------------------------------------------===// // Intrinsic creation methods //===--------------------------------------------------------------------===// @@ -285,12 +291,15 @@ public: /// If the pointers aren't i8*, they will be converted. If a TBAA tag is /// specified, it will be added to the instruction. CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0) { - return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = 0, + MDNode *TBAAStructTag = 0) { + return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, + TBAAStructTag); } CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); + bool isVolatile = false, MDNode *TBAATag = 0, + MDNode *TBAAStructTag = 0); /// CreateMemMove - Create and insert a memmove between the specified /// pointers. If the pointers aren't i8*, they will be converted. If a TBAA @@ -321,7 +330,10 @@ private: /// /// Note that the builder does not expose the full generality of LLVM /// instructions. For access to extra instruction properties, use the mutators -/// (e.g. setVolatile) on the instructions after they have been created. +/// (e.g. setVolatile) on the instructions after they have been +/// created. Convenience state exists to specify fast-math flags and fp-math +/// tags. +/// /// The first template argument handles whether or not to preserve names in the /// final instruction output. This defaults to on. The second template argument /// specifies a class to use for creating constants. This defaults to creating @@ -333,36 +345,40 @@ template<bool preserveNames = true, typename T = ConstantFolder, 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) { + : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag), + FMF() { } - explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) : IRBuilderBase(C), - Folder(), DefaultFPMathTag(FPMathTag) { + explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) + : IRBuilderBase(C), Folder(), DefaultFPMathTag(FPMathTag), FMF() { } explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0) : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag) { + DefaultFPMathTag(FPMathTag), FMF() { SetInsertPoint(TheBB); } explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0) : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag) { + DefaultFPMathTag(FPMathTag), FMF() { SetInsertPoint(TheBB); } explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0) - : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag) { + : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag), + FMF() { SetInsertPoint(IP); SetCurrentDebugLocation(IP->getDebugLoc()); } explicit IRBuilder(Use &U, MDNode *FPMathTag = 0) - : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag) { + : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag), + FMF() { SetInsertPoint(U); SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc()); } @@ -370,13 +386,13 @@ public: IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, MDNode *FPMathTag = 0) : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag) { + DefaultFPMathTag(FPMathTag), FMF() { SetInsertPoint(TheBB, IP); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0) : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag) { + DefaultFPMathTag(FPMathTag), FMF() { SetInsertPoint(TheBB, IP); } @@ -386,9 +402,18 @@ public: /// getDefaultFPMathTag - Get the floating point math metadata being used. MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } + /// Get the flags to be applied to created floating point ops + FastMathFlags getFastMathFlags() const { return FMF; } + + /// Clear the fast-math flags. + void clearFastMathFlags() { FMF.clear(); } + /// SetDefaultFPMathTag - Set the floating point math metadata to be used. void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } + /// Set the fast-math flags to be used with generated fp-math operators + void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } + /// isNamePreserving - Return true if this builder is configured to actually /// add the requested names to IR created through it. bool isNamePreserving() const { return preserveNames; } @@ -527,11 +552,14 @@ private: return BO; } - Instruction *AddFPMathTag(Instruction *I, MDNode *FPMathTag) const { + Instruction *AddFPMathAttributes(Instruction *I, + MDNode *FPMathTag, + FastMathFlags FMF) const { if (!FPMathTag) FPMathTag = DefaultFPMathTag; if (FPMathTag) I->setMetadata(LLVMContext::MD_fpmath, FPMathTag); + I->setFastMathFlags(FMF); return I; } public: @@ -554,8 +582,8 @@ public: if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFAdd(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFAdd(LHS, RHS), - FPMathTag), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFAdd(LHS, RHS), + FPMathTag, FMF), Name); } Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { @@ -576,8 +604,8 @@ public: if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFSub(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFSub(LHS, RHS), - FPMathTag), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFSub(LHS, RHS), + FPMathTag, FMF), Name); } Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { @@ -598,8 +626,8 @@ public: if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFMul(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFMul(LHS, RHS), - FPMathTag), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFMul(LHS, RHS), + FPMathTag, FMF), Name); } Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", bool isExact = false) { @@ -630,8 +658,8 @@ public: if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFDiv(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFDiv(LHS, RHS), - FPMathTag), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFDiv(LHS, RHS), + FPMathTag, FMF), Name); } Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) @@ -650,8 +678,8 @@ public: if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFRem(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFRem(LHS, RHS), - FPMathTag), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFRem(LHS, RHS), + FPMathTag, FMF), Name); } Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", @@ -780,7 +808,8 @@ public: Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = 0) { if (Constant *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateFNeg(VC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFNeg(V), FPMathTag), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFNeg(V), + FPMathTag, FMF), Name); } Value *CreateNot(Value *V, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(V)) @@ -810,6 +839,31 @@ public: StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { return Insert(new StoreInst(Val, Ptr, isVolatile)); } + // Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' correctly, + // instead of converting the string to 'bool' for the isVolatile parameter. + LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, const char *Name) { + LoadInst *LI = CreateLoad(Ptr, Name); + LI->setAlignment(Align); + return LI; + } + LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, + const Twine &Name = "") { + LoadInst *LI = CreateLoad(Ptr, Name); + LI->setAlignment(Align); + return LI; + } + LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, bool isVolatile, + const Twine &Name = "") { + LoadInst *LI = CreateLoad(Ptr, isVolatile, Name); + LI->setAlignment(Align); + return LI; + } + StoreInst *CreateAlignedStore(Value *Val, Value *Ptr, unsigned Align, + bool isVolatile = false) { + StoreInst *SI = CreateStore(Val, Ptr, isVolatile); + SI->setAlignment(Align); + return SI; + } FenceInst *CreateFence(AtomicOrdering Ordering, SynchronizationScope SynchScope = CrossThread) { return Insert(new FenceInst(Context, Ordering, SynchScope)); @@ -970,6 +1024,30 @@ public: Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::SExt, V, DestTy, Name); } + /// CreateZExtOrTrunc - Create a ZExt or Trunc from the integer value V to + /// DestTy. Return the value untouched if the type of V is already DestTy. + Value *CreateZExtOrTrunc(Value *V, IntegerType *DestTy, + const Twine &Name = "") { + assert(isa<IntegerType>(V->getType()) && "Can only zero extend integers!"); + IntegerType *IntTy = cast<IntegerType>(V->getType()); + if (IntTy->getBitWidth() < DestTy->getBitWidth()) + return CreateZExt(V, DestTy, Name); + if (IntTy->getBitWidth() > DestTy->getBitWidth()) + return CreateTrunc(V, DestTy, Name); + return V; + } + /// CreateSExtOrTrunc - Create a SExt or Trunc from the integer value V to + /// DestTy. Return the value untouched if the type of V is already DestTy. + Value *CreateSExtOrTrunc(Value *V, IntegerType *DestTy, + const Twine &Name = "") { + assert(isa<IntegerType>(V->getType()) && "Can only sign extend integers!"); + IntegerType *IntTy = cast<IntegerType>(V->getType()); + if (IntTy->getBitWidth() < DestTy->getBitWidth()) + return CreateSExt(V, DestTy, Name); + if (IntTy->getBitWidth() > DestTy->getBitWidth()) + return CreateTrunc(V, DestTy, Name); + return V; + } Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::FPToUI, V, DestTy, Name); } @@ -1052,7 +1130,7 @@ public: private: // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a compile time // error, instead of converting the string to bool for the isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *); // DO NOT IMPLEMENT + Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION; public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) @@ -1254,20 +1332,20 @@ public: LandingPadInst *CreateLandingPad(Type *Ty, Value *PersFn, unsigned NumClauses, const Twine &Name = "") { - return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses, Name)); + return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses), Name); } //===--------------------------------------------------------------------===// // Utility creation methods //===--------------------------------------------------------------------===// - /// CreateIsNull - Return an i1 value testing if \arg Arg is null. + /// CreateIsNull - Return an i1 value testing if \p Arg is null. Value *CreateIsNull(Value *Arg, const Twine &Name = "") { return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), Name); } - /// CreateIsNotNull - Return an i1 value testing if \arg Arg is not null. + /// CreateIsNotNull - Return an i1 value testing if \p Arg is not null. Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), Name); @@ -1289,6 +1367,22 @@ public: ConstantExpr::getSizeOf(ArgType->getElementType()), Name); } + + /// CreateVectorSplat - Return a vector value that contains \arg V broadcasted + /// to \p NumElts elements. + Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "") { + assert(NumElts > 0 && "Cannot splat to an empty vector!"); + + // First insert it into an undef vector so we can shuffle it. + Type *I32Ty = getInt32Ty(); + Value *Undef = UndefValue::get(VectorType::get(V->getType(), NumElts)); + V = CreateInsertElement(Undef, V, ConstantInt::get(I32Ty, 0), + Name + ".splatinsert"); + + // Shuffle the value across the desired number of elements. + Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, NumElts)); + return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); + } }; } diff --git a/include/llvm/InlineAsm.h b/include/llvm/IR/InlineAsm.h index a0aecfd..15d4fb0 100644 --- a/include/llvm/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -16,8 +16,8 @@ #ifndef LLVM_INLINEASM_H #define LLVM_INLINEASM_H -#include "llvm/Value.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/Value.h" #include <vector> namespace llvm { @@ -44,8 +44,8 @@ private: friend class ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, PointerType, InlineAsm, false>; - InlineAsm(const InlineAsm &); // do not implement - void operator=(const InlineAsm&); // do not implement + InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; + void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; std::string AsmString, Constraints; bool HasSideEffects; @@ -189,7 +189,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const InlineAsm *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() == Value::InlineAsmVal; } @@ -215,6 +214,8 @@ public: Extra_HasSideEffects = 1, Extra_IsAlignStack = 2, Extra_AsmDialect = 4, + Extra_MayLoad = 8, + Extra_MayStore = 16, // Inline asm operands map to multiple SDNode / MachineInstr operands. // The first operand is an immediate describing the asm operand, the low diff --git a/include/llvm/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 6291a6d..66bf8dd 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -16,10 +16,10 @@ #ifndef LLVM_INSTRUCTION_TYPES_H #define LLVM_INSTRUCTION_TYPES_H -#include "llvm/Instruction.h" -#include "llvm/OperandTraits.h" -#include "llvm/DerivedTypes.h" #include "llvm/ADT/Twine.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/OperandTraits.h" namespace llvm { @@ -73,7 +73,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const TerminatorInst *) { return true; } static inline bool classof(const Instruction *I) { return I->isTerminator(); } @@ -88,7 +87,7 @@ public: //===----------------------------------------------------------------------===// class UnaryInstruction : public Instruction { - void *operator new(size_t, unsigned); // Do not implement + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; protected: UnaryInstruction(Type *Ty, unsigned iType, Value *V, @@ -113,7 +112,6 @@ public: DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const UnaryInstruction *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Alloca || I->getOpcode() == Instruction::Load || @@ -138,14 +136,14 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) //===----------------------------------------------------------------------===// class BinaryOperator : public Instruction { - void *operator new(size_t, unsigned); // Do not implement + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; protected: void init(BinaryOps iType); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, const Twine &Name, Instruction *InsertBefore); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); - virtual BinaryOperator *clone_impl() const; + virtual BinaryOperator *clone_impl() const LLVM_OVERRIDE; public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -179,19 +177,19 @@ public: const Twine &Name = "") {\ return Create(Instruction::OPC, V1, V2, Name);\ } -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" #define HANDLE_BINARY_INST(N, OPC, CLASS) \ static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ const Twine &Name, BasicBlock *BB) {\ return Create(Instruction::OPC, V1, V2, Name, BB);\ } -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" #define HANDLE_BINARY_INST(N, OPC, CLASS) \ static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ const Twine &Name, Instruction *I) {\ return Create(Instruction::OPC, V1, V2, Name, I);\ } -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, const Twine &Name = "") { @@ -361,7 +359,6 @@ public: bool isExact() const; // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BinaryOperator *) { return true; } static inline bool classof(const Instruction *I) { return I->isBinaryOp(); } @@ -388,7 +385,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) /// if (isa<CastInst>(Instr)) { ... } /// @brief Base class of casting instructions. class CastInst : public UnaryInstruction { - virtual void anchor(); + virtual void anchor() LLVM_OVERRIDE; protected: /// @brief Constructor with insert-before-instruction semantics for subclasses CastInst(Type *Ty, unsigned iType, Value *S, @@ -563,7 +560,7 @@ public: /// IntPtrTy argument is used to make accurate determinations for casts /// involving Integer and Pointer types. They are no-op casts if the integer /// is the same size as the pointer. However, pointer size varies with - /// platform. Generally, the result of TargetData::getIntPtrType() should be + /// platform. Generally, the result of DataLayout::getIntPtrType() should be /// passed in. If that's not available, use Type::Int64Ty, which will make /// the isNoopCast call conservative. /// @brief Determine if the described cast is a no-op cast. @@ -591,7 +588,9 @@ public: Type *SrcTy, ///< SrcTy of 1st cast Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast Type *DstTy, ///< DstTy of 2nd cast - Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + Type *SrcIntPtrTy, ///< Integer type corresponding to Ptr SrcTy, or null + Type *MidIntPtrTy, ///< Integer type corresponding to Ptr MidTy, or null + Type *DstIntPtrTy ///< Integer type corresponding to Ptr DstTy, or null ); /// @brief Return the opcode of this CastInst @@ -611,7 +610,6 @@ public: static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy); /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const CastInst *) { return true; } static inline bool classof(const Instruction *I) { return I->isCast(); } @@ -627,8 +625,8 @@ public: /// This class is the base class for the comparison instructions. /// @brief Abstract base class of comparison instructions. class CmpInst : public Instruction { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - CmpInst(); // do not implement + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + CmpInst() LLVM_DELETED_FUNCTION; protected: CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name = "", @@ -638,7 +636,7 @@ protected: Value *LHS, Value *RHS, const Twine &Name, BasicBlock *InsertAtEnd); - virtual void Anchor() const; // Out of line virtual method. + virtual void anchor() LLVM_OVERRIDE; // Out of line virtual method. public: /// This enumeration lists the possible predicates for CmpInst subclasses. /// Values in the range 0-31 are reserved for FCmpInst, while values in the @@ -816,7 +814,6 @@ public: static bool isFalseWhenEqual(unsigned short predicate); /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const CmpInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::ICmp || I->getOpcode() == Instruction::FCmp; diff --git a/include/llvm/Instruction.def b/include/llvm/IR/Instruction.def index e59a052..e59a052 100644 --- a/include/llvm/Instruction.def +++ b/include/llvm/IR/Instruction.def diff --git a/include/llvm/Instruction.h b/include/llvm/IR/Instruction.h index 5512dcc..2731bfb 100644 --- a/include/llvm/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -15,12 +15,13 @@ #ifndef LLVM_INSTRUCTION_H #define LLVM_INSTRUCTION_H -#include "llvm/User.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/IR/User.h" #include "llvm/Support/DebugLoc.h" namespace llvm { +class FastMathFlags; class LLVMContext; class MDNode; @@ -28,12 +29,12 @@ template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; class Instruction : public User, public ilist_node<Instruction> { - void operator=(const Instruction &); // Do not implement - Instruction(const Instruction &); // Do not implement + void operator=(const Instruction &) LLVM_DELETED_FUNCTION; + Instruction(const Instruction &) LLVM_DELETED_FUNCTION; BasicBlock *Parent; DebugLoc DbgLoc; // 'dbg' Metadata cache. - + enum { /// HasMetadataBit - This is a bit stored in the SubClassData field which /// indicates whether this instruction has metadata attached to it or not. @@ -42,12 +43,12 @@ class Instruction : public User, public ilist_node<Instruction> { public: // Out of line virtual method, so the vtable, etc has a home. ~Instruction(); - + /// use_back - Specialize the methods defined in Value, as we know that an /// instruction can only be used by other instructions. Instruction *use_back() { return cast<Instruction>(*use_begin());} const Instruction *use_back() const { return cast<Instruction>(*use_begin());} - + inline const BasicBlock *getParent() const { return Parent; } inline BasicBlock *getParent() { return Parent; } @@ -77,16 +78,16 @@ public: //===--------------------------------------------------------------------===// // Subclass classification. //===--------------------------------------------------------------------===// - + /// getOpcode() returns a member of one of the enums like Instruction::Add. unsigned getOpcode() const { return getValueID() - InstructionVal; } - + const char *getOpcodeName() const { return getOpcodeName(getOpcode()); } bool isTerminator() const { return isTerminator(getOpcode()); } bool isBinaryOp() const { return isBinaryOp(getOpcode()); } bool isShift() { return isShift(getOpcode()); } bool isCast() const { return isCast(getOpcode()); } - + static const char* getOpcodeName(unsigned OpCode); static inline bool isTerminator(unsigned OpCode) { @@ -121,33 +122,33 @@ public: //===--------------------------------------------------------------------===// // Metadata manipulation. //===--------------------------------------------------------------------===// - + /// hasMetadata() - Return true if this instruction has any metadata attached /// to it. bool hasMetadata() const { return !DbgLoc.isUnknown() || hasMetadataHashEntry(); } - + /// hasMetadataOtherThanDebugLoc - Return true if this instruction has /// metadata attached to it other than a debug location. bool hasMetadataOtherThanDebugLoc() const { return hasMetadataHashEntry(); } - + /// getMetadata - Get the metadata of given kind attached to this Instruction. /// If the metadata is not found then return null. MDNode *getMetadata(unsigned KindID) const { if (!hasMetadata()) return 0; return getMetadataImpl(KindID); } - + /// getMetadata - Get the metadata of given kind attached to this Instruction. /// If the metadata is not found then return null. MDNode *getMetadata(StringRef Kind) const { if (!hasMetadata()) return 0; return getMetadataImpl(Kind); } - + /// getAllMetadata - Get all metadata attached to this Instruction. The first /// element of each pair returned is the KindID, the second element is the /// metadata value. This list is returned sorted by the KindID. @@ -155,7 +156,7 @@ public: if (hasMetadata()) getAllMetadataImpl(MDs); } - + /// getAllMetadataOtherThanDebugLoc - This does the same thing as /// getAllMetadata, except that it filters out the debug location. void getAllMetadataOtherThanDebugLoc(SmallVectorImpl<std::pair<unsigned, @@ -163,7 +164,7 @@ public: if (hasMetadataOtherThanDebugLoc()) getAllMetadataOtherThanDebugLocImpl(MDs); } - + /// setMetadata - Set the metadata of the specified kind to the specified /// node. This updates/replaces metadata if already present, or removes it if /// Node is null. @@ -172,17 +173,70 @@ public: /// setDebugLoc - Set the debug location information for this instruction. void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } - + /// getDebugLoc - Return the debug location for this node as a DebugLoc. const DebugLoc &getDebugLoc() const { return DbgLoc; } - + + /// Set or clear the unsafe-algebra flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasUnsafeAlgebra(bool B); + + /// Set or clear the no-nans flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoNaNs(bool B); + + /// Set or clear the no-infs flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoInfs(bool B); + + /// Set or clear the no-signed-zeros flag on this instruction, which must be + /// an operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoSignedZeros(bool B); + + /// Set or clear the allow-reciprocal flag on this instruction, which must be + /// an operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasAllowReciprocal(bool B); + + /// Convenience function for setting all the fast-math flags on this + /// instruction, which must be an operator which supports these flags. See + /// LangRef.html for the meaning of these flats. + void setFastMathFlags(FastMathFlags FMF); + + /// Determine whether the unsafe-algebra flag is set. + bool hasUnsafeAlgebra() const; + + /// Determine whether the no-NaNs flag is set. + bool hasNoNaNs() const; + + /// Determine whether the no-infs flag is set. + bool hasNoInfs() const; + + /// Determine whether the no-signed-zeros flag is set. + bool hasNoSignedZeros() const; + + /// Determine whether the allow-reciprocal flag is set. + bool hasAllowReciprocal() const; + + /// Convenience function for getting all the fast-math flags, which must be an + /// operator which supports these flags. See LangRef.html for the meaning of + /// these flats. + FastMathFlags getFastMathFlags() const; + + /// Copy I's fast-math flags + void copyFastMathFlags(const Instruction *I); + private: /// hasMetadataHashEntry - Return true if we have an entry in the on-the-side /// metadata hash. bool hasMetadataHashEntry() const { return (getSubclassDataFromValue() & HasMetadataBit) != 0; } - + // These are all implemented in Metadata.cpp. MDNode *getMetadataImpl(unsigned KindID) const; MDNode *getMetadataImpl(StringRef Kind) const; @@ -194,15 +248,15 @@ public: //===--------------------------------------------------------------------===// // Predicates and helper methods. //===--------------------------------------------------------------------===// - - + + /// isAssociative - Return true if the instruction is associative: /// /// Associative operators satisfy: x op (y op z) === (x op y) op z /// /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative. /// - bool isAssociative() const { return isAssociative(getOpcode()); } + bool isAssociative() const; static bool isAssociative(unsigned op); /// isCommutative - Return true if the instruction is commutative: @@ -271,12 +325,12 @@ public: /// * The instruction has no name /// Instruction *clone() const; - + /// isIdenticalTo - Return true if the specified instruction is exactly /// identical to the current one. This means that all operands match and any /// extra information (e.g. load is volatile) agree. bool isIdenticalTo(const Instruction *I) const; - + /// isIdenticalToWhenDefined - This is like isIdenticalTo, except that it /// ignores the SubclassOptionalData flags, which specify conditions /// under which the instruction's result is undefined. @@ -291,7 +345,7 @@ public: /// as equivalent. CompareUsingScalarTypes = 1<<1 }; - + /// This function determines if the specified instruction executes the same /// operation as the current one. This means that the opcodes, type, operand /// types and any other factors affecting the operation must be the same. This @@ -301,16 +355,15 @@ public: /// the current one. /// @brief Determine if one instruction is the same operation as another. bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const; - + /// isUsedOutsideOfBlock - Return true if there are any uses of this /// instruction in blocks other than the specified block. Note that PHI nodes /// are considered to evaluate their operands in the corresponding predecessor /// block. bool isUsedOutsideOfBlock(const BasicBlock *BB) const; - - + + /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Instruction *) { return true; } static inline bool classof(const Value *V) { return V->getValueID() >= Value::InstructionVal; } @@ -322,35 +375,35 @@ public: #define FIRST_TERM_INST(N) TermOpsBegin = N, #define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N, #define LAST_TERM_INST(N) TermOpsEnd = N+1 -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" }; enum BinaryOps { #define FIRST_BINARY_INST(N) BinaryOpsBegin = N, #define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N, #define LAST_BINARY_INST(N) BinaryOpsEnd = N+1 -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" }; enum MemoryOps { #define FIRST_MEMORY_INST(N) MemoryOpsBegin = N, #define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N, #define LAST_MEMORY_INST(N) MemoryOpsEnd = N+1 -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" }; enum CastOps { #define FIRST_CAST_INST(N) CastOpsBegin = N, #define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N, #define LAST_CAST_INST(N) CastOpsEnd = N+1 -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" }; enum OtherOps { #define FIRST_OTHER_INST(N) OtherOpsBegin = N, #define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N, #define LAST_OTHER_INST(N) OtherOpsEnd = N+1 -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" }; private: // Shadow Value::setValueSubclassData with a private forwarding method so that @@ -361,34 +414,34 @@ private: unsigned short getSubclassDataFromValue() const { return Value::getSubclassDataFromValue(); } - + void setHasMetadataHashEntry(bool V) { setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) | (V ? HasMetadataBit : 0)); } - + friend class SymbolTableListTraits<Instruction, BasicBlock>; void setParent(BasicBlock *P); protected: // Instruction subclasses can stick up to 15 bits of stuff into the // SubclassData field of instruction with these members. - + // Verify that only the low 15 bits are used. void setInstructionSubclassData(unsigned short D) { assert((D & HasMetadataBit) == 0 && "Out of range value put into field"); setValueSubclassData((getSubclassDataFromValue() & HasMetadataBit) | D); } - + unsigned getSubclassDataFromInstruction() const { return getSubclassDataFromValue() & ~HasMetadataBit; } - + Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, Instruction *InsertBefore = 0); Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd); virtual Instruction *clone_impl() const = 0; - + }; // Instruction* is only 4-byte aligned. @@ -402,7 +455,7 @@ public: } enum { NumLowBitsAvailable = 2 }; }; - + } // End llvm namespace #endif diff --git a/include/llvm/Instructions.h b/include/llvm/IR/Instructions.h index f5187e6..bb4ea55 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -16,22 +16,23 @@ #ifndef LLVM_INSTRUCTIONS_H #define LLVM_INSTRUCTIONS_H -#include "llvm/InstrTypes.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Attributes.h" -#include "llvm/CallingConv.h" -#include "llvm/Support/IntegersSubset.h" -#include "llvm/Support/IntegersSubsetMapping.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/CallingConv.h" +#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 { +class APInt; class ConstantInt; class ConstantRange; -class APInt; +class DataLayout; class LLVMContext; enum AtomicOrdering { @@ -112,7 +113,6 @@ public: bool isStaticAlloca() const; // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const AllocaInst *) { return true; } static inline bool classof(const Instruction *I) { return (I->getOpcode() == Instruction::Alloca); } @@ -226,13 +226,13 @@ public: const Value *getPointerOperand() const { return getOperand(0); } static unsigned getPointerOperandIndex() { return 0U; } + /// \brief Returns the address space of the pointer operand. unsigned getPointerAddressSpace() const { - return cast<PointerType>(getPointerOperand()->getType())->getAddressSpace(); + return getPointerOperand()->getType()->getPointerAddressSpace(); } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const LoadInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Load; } @@ -255,7 +255,7 @@ private: /// StoreInst - an instruction for storing to memory /// class StoreInst : public Instruction { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void AssertOK(); protected: virtual StoreInst *clone_impl() const; @@ -349,12 +349,12 @@ public: const Value *getPointerOperand() const { return getOperand(1); } static unsigned getPointerOperandIndex() { return 1U; } + /// \brief Returns the address space of the pointer operand. unsigned getPointerAddressSpace() const { - return cast<PointerType>(getPointerOperand()->getType())->getAddressSpace(); + return getPointerOperand()->getType()->getPointerAddressSpace(); } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const StoreInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Store; } @@ -382,7 +382,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) /// FenceInst - an instruction for ordering other memory operations /// class FenceInst : public Instruction { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: virtual FenceInst *clone_impl() const; @@ -426,7 +426,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const FenceInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Fence; } @@ -450,7 +449,7 @@ private: /// there. Returns the value that was loaded. /// class AtomicCmpXchgInst : public Instruction { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void Init(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: @@ -521,12 +520,12 @@ public: Value *getNewValOperand() { return getOperand(2); } const Value *getNewValOperand() const { return getOperand(2); } + /// \brief Returns the address space of the pointer operand. unsigned getPointerAddressSpace() const { - return cast<PointerType>(getPointerOperand()->getType())->getAddressSpace(); + return getPointerOperand()->getType()->getPointerAddressSpace(); } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const AtomicCmpXchgInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::AtomicCmpXchg; } @@ -557,7 +556,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) /// the old value. /// class AtomicRMWInst : public Instruction { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; protected: virtual AtomicRMWInst *clone_impl() const; public: @@ -665,12 +664,12 @@ public: Value *getValOperand() { return getOperand(1); } const Value *getValOperand() const { return getOperand(1); } + /// \brief Returns the address space of the pointer operand. unsigned getPointerAddressSpace() const { - return cast<PointerType>(getPointerOperand()->getType())->getAddressSpace(); + return getPointerOperand()->getType()->getPointerAddressSpace(); } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const AtomicRMWInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::AtomicRMW; } @@ -768,6 +767,13 @@ public: return reinterpret_cast<PointerType*>(Instruction::getType()); } + /// \brief Returns the address space of this instruction's pointer type. + unsigned getAddressSpace() const { + // Note that this is always the same as the pointer operand's address space + // and that is cheaper to compute, so cheat here. + return getPointerAddressSpace(); + } + /// getIndexedType - Returns the type of the element that would be loaded with /// a load instruction with the specified parameters. /// @@ -778,10 +784,6 @@ public: static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList); static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList); - /// getIndexedType - Returns the address space used by the GEP pointer. - /// - static unsigned getAddressSpace(Value *Ptr); - inline op_iterator idx_begin() { return op_begin()+1; } inline const_op_iterator idx_begin() const { return op_begin()+1; } inline op_iterator idx_end() { return op_end(); } @@ -797,22 +799,23 @@ public: return 0U; // get index for modifying correct operand. } - unsigned getPointerAddressSpace() const { - return cast<PointerType>(getType())->getAddressSpace(); - } - /// getPointerOperandType - Method to return the pointer operand as a /// PointerType. Type *getPointerOperandType() const { return getPointerOperand()->getType(); } + /// \brief Returns the address space of the pointer operand. + unsigned getPointerAddressSpace() const { + return getPointerOperandType()->getPointerAddressSpace(); + } + /// GetGEPReturnType - Returns the pointer type returned by the GEP /// instruction, which may be a vector of pointers. static Type *getGEPReturnType(Value *Ptr, ArrayRef<Value *> IdxList) { Type *PtrTy = PointerType::get(checkGEPType( getIndexedType(Ptr->getType(), IdxList)), - getAddressSpace(Ptr)); + Ptr->getType()->getPointerAddressSpace()); // Vector GEP if (Ptr->getType()->isVectorTy()) { unsigned NumElem = cast<VectorType>(Ptr->getType())->getNumElements(); @@ -848,8 +851,17 @@ public: /// isInBounds - Determine whether the GEP has the inbounds flag. bool isInBounds() const; + /// \brief Accumulate the constant address offset of this GEP if possible. + /// + /// This routine accepts an APInt into which it will accumulate the constant + /// 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. + bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const; + // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const GetElementPtrInst *) { return true; } static inline bool classof(const Instruction *I) { return (I->getOpcode() == Instruction::GetElementPtr); } @@ -897,13 +909,13 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) /// This instruction compares its operands according to the predicate given /// to the constructor. It only operates on integers or pointers. The operands /// must be identical types. -/// @brief Represent an integer comparison operator. +/// \brief Represent an integer comparison operator. class ICmpInst: public CmpInst { protected: - /// @brief Clone an identical ICmpInst + /// \brief Clone an identical ICmpInst virtual ICmpInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics. + /// \brief Constructor with insert-before-instruction semantics. ICmpInst( Instruction *InsertBefore, ///< Where to insert Predicate pred, ///< The predicate to use for the comparison @@ -924,7 +936,7 @@ public: "Invalid operand types for ICmp instruction"); } - /// @brief Constructor with insert-at-end semantics. + /// \brief Constructor with insert-at-end semantics. ICmpInst( BasicBlock &InsertAtEnd, ///< Block to insert into. Predicate pred, ///< The predicate to use for the comparison @@ -945,7 +957,7 @@ public: "Invalid operand types for ICmp instruction"); } - /// @brief Constructor with no-insertion semantics + /// \brief Constructor with no-insertion semantics ICmpInst( Predicate pred, ///< The predicate to use for the comparison Value *LHS, ///< The left-hand-side of the expression @@ -967,25 +979,25 @@ public: /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. /// @returns the predicate that would be the result if the operand were /// regarded as signed. - /// @brief Return the signed version of the predicate + /// \brief Return the signed version of the predicate Predicate getSignedPredicate() const { return getSignedPredicate(getPredicate()); } /// This is a static version that you can use without an instruction. - /// @brief Return the signed version of the predicate. + /// \brief Return the signed version of the predicate. static Predicate getSignedPredicate(Predicate pred); /// For example, EQ->EQ, SLE->ULE, UGT->UGT, etc. /// @returns the predicate that would be the result if the operand were /// regarded as unsigned. - /// @brief Return the unsigned version of the predicate + /// \brief Return the unsigned version of the predicate Predicate getUnsignedPredicate() const { return getUnsignedPredicate(getPredicate()); } /// This is a static version that you can use without an instruction. - /// @brief Return the unsigned version of the predicate. + /// \brief Return the unsigned version of the predicate. static Predicate getUnsignedPredicate(Predicate pred); /// isEquality - Return true if this predicate is either EQ or NE. This also @@ -1001,7 +1013,7 @@ public: } /// @returns true if the predicate of this ICmpInst is commutative - /// @brief Determine if this relation is commutative. + /// \brief Determine if this relation is commutative. bool isCommutative() const { return isEquality(); } /// isRelational - Return true if the predicate is relational (not EQ or NE). @@ -1017,21 +1029,20 @@ public: } /// Initialize a set of values that all satisfy the predicate with C. - /// @brief Make a ConstantRange for a relation with a constant value. + /// \brief Make a ConstantRange for a relation with a constant value. static ConstantRange makeConstantRange(Predicate pred, const APInt &C); /// Exchange the two operands to this instruction in such a way that it does /// not modify the semantics of the instruction. The predicate value may be /// changed to retain the same result if the predicate is order dependent /// (e.g. ult). - /// @brief Swap operands and adjust predicate. + /// \brief Swap operands and adjust predicate. void swapOperands() { setPredicate(getSwappedPredicate()); Op<0>().swap(Op<1>()); } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ICmpInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::ICmp; } @@ -1048,13 +1059,13 @@ public: /// This instruction compares its operands according to the predicate given /// to the constructor. It only operates on floating point values or packed /// vectors of floating point values. The operands must be identical types. -/// @brief Represents a floating point comparison operator. +/// \brief Represents a floating point comparison operator. class FCmpInst: public CmpInst { protected: - /// @brief Clone an identical FCmpInst + /// \brief Clone an identical FCmpInst virtual FCmpInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics. + /// \brief Constructor with insert-before-instruction semantics. FCmpInst( Instruction *InsertBefore, ///< Where to insert Predicate pred, ///< The predicate to use for the comparison @@ -1073,7 +1084,7 @@ public: "Invalid operand types for FCmp instruction"); } - /// @brief Constructor with insert-at-end semantics. + /// \brief Constructor with insert-at-end semantics. FCmpInst( BasicBlock &InsertAtEnd, ///< Block to insert into. Predicate pred, ///< The predicate to use for the comparison @@ -1092,7 +1103,7 @@ public: "Invalid operand types for FCmp instruction"); } - /// @brief Constructor with no-insertion semantics + /// \brief Constructor with no-insertion semantics FCmpInst( Predicate pred, ///< The predicate to use for the comparison Value *LHS, ///< The left-hand-side of the expression @@ -1110,14 +1121,14 @@ public: } /// @returns true if the predicate of this instruction is EQ or NE. - /// @brief Determine if this is an equality predicate. + /// \brief Determine if this is an equality predicate. bool isEquality() const { return getPredicate() == FCMP_OEQ || getPredicate() == FCMP_ONE || getPredicate() == FCMP_UEQ || getPredicate() == FCMP_UNE; } /// @returns true if the predicate of this instruction is commutative. - /// @brief Determine if this is a commutative predicate. + /// \brief Determine if this is a commutative predicate. bool isCommutative() const { return isEquality() || getPredicate() == FCMP_FALSE || @@ -1127,21 +1138,20 @@ public: } /// @returns true if the predicate is relational (not EQ or NE). - /// @brief Determine if this a relational predicate. + /// \brief Determine if this a relational predicate. bool isRelational() const { return !isEquality(); } /// Exchange the two operands to this instruction in such a way that it does /// not modify the semantics of the instruction. The predicate value may be /// changed to retain the same result if the predicate is order dependent /// (e.g. ult). - /// @brief Swap operands and adjust predicate. + /// \brief Swap operands and adjust predicate. void swapOperands() { setPredicate(getSwappedPredicate()); Op<0>().swap(Op<1>()); } - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const FCmpInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::FCmp; } @@ -1157,18 +1167,18 @@ public: /// hold the calling convention of the call. /// class CallInst : public Instruction { - AttrListPtr AttributeList; ///< parameter attributes for call + AttributeSet AttributeList; ///< parameter attributes for call CallInst(const CallInst &CI); void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr); void init(Value *Func, const Twine &NameStr); /// Construct a CallInst given a range of arguments. - /// @brief Construct a CallInst from a range of arguments + /// \brief Construct a CallInst from a range of arguments inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, Instruction *InsertBefore); /// Construct a CallInst given a range of arguments. - /// @brief Construct a CallInst from a range of arguments + /// \brief Construct a CallInst from a range of arguments inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, BasicBlock *InsertAtEnd); @@ -1255,87 +1265,92 @@ public: /// getAttributes - Return the parameter attributes for this call. /// - const AttrListPtr &getAttributes() const { return AttributeList; } + const AttributeSet &getAttributes() const { return AttributeList; } /// setAttributes - Set the parameter attributes for this call. /// - void setAttributes(const AttrListPtr &Attrs) { AttributeList = Attrs; } + void setAttributes(const AttributeSet &Attrs) { AttributeList = Attrs; } /// addAttribute - adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attributes attr); + void addAttribute(unsigned i, Attribute attr); /// removeAttribute - removes the attribute from the list of attributes. - void removeAttribute(unsigned i, Attributes attr); + void removeAttribute(unsigned i, Attribute attr); - /// \brief Return true if this call has the given attribute. - bool hasFnAttr(Attributes N) const { - return paramHasAttr(~0, N); - } + /// \brief Determine whether this call has the given attribute. + bool hasFnAttr(Attribute::AttrKind A) const; - /// @brief Determine whether the call or the callee has the given attribute. - bool paramHasAttr(unsigned i, Attributes attr) const; + /// \brief Determine whether the call or the callee has the given attributes. + bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; - /// @brief Extract the alignment for a call or parameter (0=unknown). + /// \brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeList.getParamAlignment(i); } - /// @brief Return true if the call should not be inlined. + /// \brief Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } - void setIsNoInline(bool Value = true) { - if (Value) addAttribute(~0, Attribute::NoInline); - else removeAttribute(~0, Attribute::NoInline); + void setIsNoInline() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::NoInline)); } - /// @brief Return true if the call can return twice + /// \brief Return true if the call can return twice bool canReturnTwice() const { return hasFnAttr(Attribute::ReturnsTwice); } - void setCanReturnTwice(bool Value = true) { - if (Value) addAttribute(~0, Attribute::ReturnsTwice); - else removeAttribute(~0, Attribute::ReturnsTwice); + void setCanReturnTwice() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::ReturnsTwice)); } - /// @brief Determine if the call does not access memory. + /// \brief Determine if the call does not access memory. bool doesNotAccessMemory() const { return hasFnAttr(Attribute::ReadNone); } - void setDoesNotAccessMemory(bool NotAccessMemory = true) { - if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); - else removeAttribute(~0, Attribute::ReadNone); + void setDoesNotAccessMemory() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::ReadNone)); } - /// @brief Determine if the call does not access or only reads memory. + /// \brief Determine if the call does not access or only reads memory. bool onlyReadsMemory() const { return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); } - void setOnlyReadsMemory(bool OnlyReadsMemory = true) { - if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); - else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); + void setOnlyReadsMemory() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::ReadOnly)); } - /// @brief Determine if the call cannot return. + /// \brief Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } - void setDoesNotReturn(bool DoesNotReturn = true) { - if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); - else removeAttribute(~0, Attribute::NoReturn); + void setDoesNotReturn() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::NoReturn)); } - /// @brief Determine if the call cannot unwind. + /// \brief Determine if the call cannot unwind. bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } - void setDoesNotThrow(bool DoesNotThrow = true) { - if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); - else removeAttribute(~0, Attribute::NoUnwind); + void setDoesNotThrow() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::NoUnwind)); + } + + /// \brief Determine if the call cannot be duplicated. + bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); } + void setCannotDuplicate() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::NoDuplicate)); } - /// @brief Determine if the call returns a structure through first + /// \brief Determine if the call returns a structure through first /// pointer argument. bool hasStructRetAttr() const { // Be friendly and also check the callee. return paramHasAttr(1, Attribute::StructRet); } - /// @brief Determine if any call argument is an aggregate passed by value. + /// \brief Determine if any call argument is an aggregate passed by value. bool hasByValArgument() const { return AttributeList.hasAttrSomewhere(Attribute::ByVal); } @@ -1363,7 +1378,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const CallInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Call; } @@ -1469,7 +1483,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SelectInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Select; } @@ -1512,7 +1525,6 @@ public: static unsigned getPointerOperandIndex() { return 0U; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const VAArgInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == VAArg; } @@ -1566,7 +1578,6 @@ public: DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ExtractElementInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::ExtractElement; } @@ -1625,7 +1636,6 @@ public: DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const InsertElementInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::InsertElement; } @@ -1706,7 +1716,6 @@ public: // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ShuffleVectorInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::ShuffleVector; } @@ -1802,7 +1811,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ExtractValueInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::ExtractValue; } @@ -1839,7 +1847,7 @@ ExtractValueInst::ExtractValueInst(Value *Agg, class InsertValueInst : public Instruction { SmallVector<unsigned, 4> Indices; - void *operator new(size_t, unsigned); // Do not implement + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; InsertValueInst(const InsertValueInst &IVI); void init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, const Twine &NameStr); @@ -1924,7 +1932,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const InsertValueInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::InsertValue; } @@ -1970,7 +1977,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) // scientist's overactive imagination. // class PHINode : public Instruction { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; /// ReservedSpace - The number of operands actually allocated. NumOperands is /// the number actually in use. unsigned ReservedSpace; @@ -2141,7 +2148,6 @@ public: Value *hasConstantValue() const; /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const PHINode *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::PHI; } @@ -2178,7 +2184,7 @@ class LandingPadInst : public Instruction { public: enum ClauseType { Catch, Filter }; private: - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; // Allocate space for exactly zero operands. void *operator new(size_t s) { return User::operator new(s, 0); @@ -2249,7 +2255,6 @@ public: void reserveClauses(unsigned Size) { growOperands(Size); } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const LandingPadInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::LandingPad; } @@ -2318,7 +2323,6 @@ public: unsigned getNumSuccessors() const { return 0; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ReturnInst *) { return true; } static inline bool classof(const Instruction *I) { return (I->getOpcode() == Instruction::Ret); } @@ -2418,7 +2422,6 @@ public: void swapSuccessors(); // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BranchInst *) { return true; } static inline bool classof(const Instruction *I) { return (I->getOpcode() == Instruction::Br); } @@ -2445,7 +2448,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) /// SwitchInst - Multiway switch /// class SwitchInst : public TerminatorInst { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; unsigned ReservedSpace; // Operands format: // Operand[0] = Value to switch on @@ -2613,7 +2616,7 @@ public: } /// addCase - Add an entry to the switch instruction... - /// @Deprecated + /// @deprecated /// Note: /// This action invalidates case_end(). Old case_end() iterator will /// point to the added case. @@ -2699,7 +2702,7 @@ public: } /// Resolves case value for current case. - /// @Deprecated + /// @deprecated ConstantIntTy *getCaseValue() { assert(Index < SI->getNumCases() && "Index out the number of cases."); IntegersSubsetRef CaseRanges = *SubsetIt; @@ -2803,7 +2806,7 @@ public: CaseIt(const ParentTy& Src) : ParentTy(Src) {} /// Sets the new value for current case. - /// @Deprecated. + /// @deprecated. void setValue(ConstantInt *V) { assert(Index < SI->getNumCases() && "Index out the number of cases."); IntegersSubsetToBB Mapping; @@ -2829,7 +2832,6 @@ public: // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SwitchInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Switch; } @@ -2857,7 +2859,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) /// IndirectBrInst - Indirect Branch Instruction. /// class IndirectBrInst : public TerminatorInst { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -2928,7 +2930,6 @@ public: } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const IndirectBrInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::IndirectBr; } @@ -2956,21 +2957,21 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) /// calling convention of the call. /// class InvokeInst : public TerminatorInst { - AttrListPtr AttributeList; + AttributeSet AttributeList; InvokeInst(const InvokeInst &BI); void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, const Twine &NameStr); /// Construct an InvokeInst given a range of arguments. /// - /// @brief Construct an InvokeInst from a range of arguments + /// \brief Construct an InvokeInst from a range of arguments inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, unsigned Values, const Twine &NameStr, Instruction *InsertBefore); /// Construct an InvokeInst given a range of arguments. /// - /// @brief Construct an InvokeInst from a range of arguments + /// \brief Construct an InvokeInst from a range of arguments inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); @@ -3017,78 +3018,76 @@ public: /// getAttributes - Return the parameter attributes for this invoke. /// - const AttrListPtr &getAttributes() const { return AttributeList; } + const AttributeSet &getAttributes() const { return AttributeList; } /// setAttributes - Set the parameter attributes for this invoke. /// - void setAttributes(const AttrListPtr &Attrs) { AttributeList = Attrs; } + void setAttributes(const AttributeSet &Attrs) { AttributeList = Attrs; } /// addAttribute - adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attributes attr); + void addAttribute(unsigned i, Attribute attr); /// removeAttribute - removes the attribute from the list of attributes. - void removeAttribute(unsigned i, Attributes attr); + void removeAttribute(unsigned i, Attribute attr); - /// \brief Return true if this call has the given attribute. - bool hasFnAttr(Attributes N) const { - return paramHasAttr(~0, N); - } + /// \brief Determine whether this call has the NoAlias attribute. + bool hasFnAttr(Attribute::AttrKind A) const; - /// @brief Determine whether the call or the callee has the given attribute. - bool paramHasAttr(unsigned i, Attributes attr) const; + /// \brief Determine whether the call or the callee has the given attributes. + bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; - /// @brief Extract the alignment for a call or parameter (0=unknown). + /// \brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeList.getParamAlignment(i); } - /// @brief Return true if the call should not be inlined. + /// \brief Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } - void setIsNoInline(bool Value = true) { - if (Value) addAttribute(~0, Attribute::NoInline); - else removeAttribute(~0, Attribute::NoInline); + void setIsNoInline() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::NoInline)); } - /// @brief Determine if the call does not access memory. + /// \brief Determine if the call does not access memory. bool doesNotAccessMemory() const { return hasFnAttr(Attribute::ReadNone); } - void setDoesNotAccessMemory(bool NotAccessMemory = true) { - if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); - else removeAttribute(~0, Attribute::ReadNone); + void setDoesNotAccessMemory() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::ReadNone)); } - /// @brief Determine if the call does not access or only reads memory. + /// \brief Determine if the call does not access or only reads memory. bool onlyReadsMemory() const { return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); } - void setOnlyReadsMemory(bool OnlyReadsMemory = true) { - if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); - else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); + void setOnlyReadsMemory() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::ReadOnly)); } - /// @brief Determine if the call cannot return. + /// \brief Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } - void setDoesNotReturn(bool DoesNotReturn = true) { - if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); - else removeAttribute(~0, Attribute::NoReturn); + void setDoesNotReturn() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::NoReturn)); } - /// @brief Determine if the call cannot unwind. + /// \brief Determine if the call cannot unwind. bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } - void setDoesNotThrow(bool DoesNotThrow = true) { - if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); - else removeAttribute(~0, Attribute::NoUnwind); + void setDoesNotThrow() { + addAttribute(AttributeSet::FunctionIndex, + Attribute::get(getContext(), Attribute::NoUnwind)); } - /// @brief Determine if the call returns a structure through first + /// \brief Determine if the call returns a structure through first /// pointer argument. bool hasStructRetAttr() const { // Be friendly and also check the callee. return paramHasAttr(1, Attribute::StructRet); } - /// @brief Determine if any call argument is an aggregate passed by value. + /// \brief Determine if any call argument is an aggregate passed by value. bool hasByValArgument() const { return AttributeList.hasAttrSomewhere(Attribute::ByVal); } @@ -3141,7 +3140,6 @@ public: unsigned getNumSuccessors() const { return 2; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const InvokeInst *) { return true; } static inline bool classof(const Instruction *I) { return (I->getOpcode() == Instruction::Invoke); } @@ -3221,7 +3219,6 @@ public: unsigned getNumSuccessors() const { return 0; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ResumeInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Resume; } @@ -3251,7 +3248,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) /// end of the block cannot be reached. /// class UnreachableInst : public TerminatorInst { - void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; protected: virtual UnreachableInst *clone_impl() const; @@ -3266,7 +3263,6 @@ public: unsigned getNumSuccessors() const { return 0; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const UnreachableInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Unreachable; } @@ -3283,14 +3279,14 @@ private: // TruncInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a truncation of integer types. +/// \brief This class represents a truncation of integer types. class TruncInst : public CastInst { protected: - /// @brief Clone an identical TruncInst + /// \brief Clone an identical TruncInst virtual TruncInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics TruncInst( Value *S, ///< The value to be truncated Type *Ty, ///< The (smaller) type to truncate to @@ -3298,7 +3294,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics TruncInst( Value *S, ///< The value to be truncated Type *Ty, ///< The (smaller) type to truncate to @@ -3306,8 +3302,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const TruncInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == Trunc; } @@ -3320,14 +3315,14 @@ public: // ZExtInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents zero extension of integer types. +/// \brief This class represents zero extension of integer types. class ZExtInst : public CastInst { protected: - /// @brief Clone an identical ZExtInst + /// \brief Clone an identical ZExtInst virtual ZExtInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics ZExtInst( Value *S, ///< The value to be zero extended Type *Ty, ///< The type to zero extend to @@ -3335,7 +3330,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end semantics. + /// \brief Constructor with insert-at-end semantics. ZExtInst( Value *S, ///< The value to be zero extended Type *Ty, ///< The type to zero extend to @@ -3343,8 +3338,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ZExtInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == ZExt; } @@ -3357,14 +3351,14 @@ public: // SExtInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a sign extension of integer types. +/// \brief This class represents a sign extension of integer types. class SExtInst : public CastInst { protected: - /// @brief Clone an identical SExtInst + /// \brief Clone an identical SExtInst virtual SExtInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics SExtInst( Value *S, ///< The value to be sign extended Type *Ty, ///< The type to sign extend to @@ -3372,7 +3366,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics SExtInst( Value *S, ///< The value to be sign extended Type *Ty, ///< The type to sign extend to @@ -3380,8 +3374,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SExtInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == SExt; } @@ -3394,14 +3387,14 @@ public: // FPTruncInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a truncation of floating point types. +/// \brief This class represents a truncation of floating point types. class FPTruncInst : public CastInst { protected: - /// @brief Clone an identical FPTruncInst + /// \brief Clone an identical FPTruncInst virtual FPTruncInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics FPTruncInst( Value *S, ///< The value to be truncated Type *Ty, ///< The type to truncate to @@ -3409,7 +3402,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics FPTruncInst( Value *S, ///< The value to be truncated Type *Ty, ///< The type to truncate to @@ -3417,8 +3410,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const FPTruncInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == FPTrunc; } @@ -3431,14 +3423,14 @@ public: // FPExtInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents an extension of floating point types. +/// \brief This class represents an extension of floating point types. class FPExtInst : public CastInst { protected: - /// @brief Clone an identical FPExtInst + /// \brief Clone an identical FPExtInst virtual FPExtInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics FPExtInst( Value *S, ///< The value to be extended Type *Ty, ///< The type to extend to @@ -3446,7 +3438,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics FPExtInst( Value *S, ///< The value to be extended Type *Ty, ///< The type to extend to @@ -3454,8 +3446,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const FPExtInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == FPExt; } @@ -3468,14 +3459,14 @@ public: // UIToFPInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a cast unsigned integer to floating point. +/// \brief This class represents a cast unsigned integer to floating point. class UIToFPInst : public CastInst { protected: - /// @brief Clone an identical UIToFPInst + /// \brief Clone an identical UIToFPInst virtual UIToFPInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics UIToFPInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3483,7 +3474,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics UIToFPInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3491,8 +3482,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const UIToFPInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == UIToFP; } @@ -3505,14 +3495,14 @@ public: // SIToFPInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a cast from signed integer to floating point. +/// \brief This class represents a cast from signed integer to floating point. class SIToFPInst : public CastInst { protected: - /// @brief Clone an identical SIToFPInst + /// \brief Clone an identical SIToFPInst virtual SIToFPInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics SIToFPInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3520,7 +3510,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics SIToFPInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3528,8 +3518,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SIToFPInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == SIToFP; } @@ -3542,14 +3531,14 @@ public: // FPToUIInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a cast from floating point to unsigned integer +/// \brief This class represents a cast from floating point to unsigned integer class FPToUIInst : public CastInst { protected: - /// @brief Clone an identical FPToUIInst + /// \brief Clone an identical FPToUIInst virtual FPToUIInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics FPToUIInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3557,7 +3546,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics FPToUIInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3565,8 +3554,7 @@ public: BasicBlock *InsertAtEnd ///< Where to insert the new instruction ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const FPToUIInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == FPToUI; } @@ -3579,14 +3567,14 @@ public: // FPToSIInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a cast from floating point to signed integer. +/// \brief This class represents a cast from floating point to signed integer. class FPToSIInst : public CastInst { protected: - /// @brief Clone an identical FPToSIInst + /// \brief Clone an identical FPToSIInst virtual FPToSIInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics FPToSIInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3594,7 +3582,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics FPToSIInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3602,8 +3590,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const FPToSIInst *) { return true; } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == FPToSI; } @@ -3616,10 +3603,10 @@ public: // IntToPtrInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a cast from an integer to a pointer. +/// \brief This class represents a cast from an integer to a pointer. class IntToPtrInst : public CastInst { public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics IntToPtrInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3627,7 +3614,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics IntToPtrInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3635,11 +3622,15 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Clone an identical IntToPtrInst + /// \brief Clone an identical IntToPtrInst virtual IntToPtrInst *clone_impl() const; + /// \brief Returns the address space of this instruction's pointer type. + unsigned getAddressSpace() const { + return getType()->getPointerAddressSpace(); + } + // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const IntToPtrInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == IntToPtr; } @@ -3652,14 +3643,14 @@ public: // PtrToIntInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a cast from a pointer to an integer +/// \brief This class represents a cast from a pointer to an integer class PtrToIntInst : public CastInst { protected: - /// @brief Clone an identical PtrToIntInst + /// \brief Clone an identical PtrToIntInst virtual PtrToIntInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics PtrToIntInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3667,7 +3658,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics PtrToIntInst( Value *S, ///< The value to be converted Type *Ty, ///< The type to convert to @@ -3675,8 +3666,19 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); + /// \brief Gets the pointer operand. + Value *getPointerOperand() { return getOperand(0); } + /// \brief Gets the pointer operand. + const Value *getPointerOperand() const { return getOperand(0); } + /// \brief Gets the operand index of the pointer operand. + static unsigned getPointerOperandIndex() { return 0U; } + + /// \brief Returns the address space of the pointer operand. + unsigned getPointerAddressSpace() const { + return getPointerOperand()->getType()->getPointerAddressSpace(); + } + // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const PtrToIntInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == PtrToInt; } @@ -3689,14 +3691,14 @@ public: // BitCastInst Class //===----------------------------------------------------------------------===// -/// @brief This class represents a no-op cast from one type to another. +/// \brief This class represents a no-op cast from one type to another. class BitCastInst : public CastInst { protected: - /// @brief Clone an identical BitCastInst + /// \brief Clone an identical BitCastInst virtual BitCastInst *clone_impl() const; public: - /// @brief Constructor with insert-before-instruction semantics + /// \brief Constructor with insert-before-instruction semantics BitCastInst( Value *S, ///< The value to be casted Type *Ty, ///< The type to casted to @@ -3704,7 +3706,7 @@ public: Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); - /// @brief Constructor with insert-at-end-of-block semantics + /// \brief Constructor with insert-at-end-of-block semantics BitCastInst( Value *S, ///< The value to be casted Type *Ty, ///< The type to casted to @@ -3713,7 +3715,6 @@ public: ); // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BitCastInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == BitCast; } diff --git a/include/llvm/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index 1cebdd2..a8dfcbd 100644 --- a/include/llvm/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -24,19 +24,19 @@ #ifndef LLVM_INTRINSICINST_H #define LLVM_INTRINSICINST_H -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" namespace llvm { /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic /// functions. This allows the standard isa/dyncast/cast functionality to /// work with calls to intrinsic functions. class IntrinsicInst : public CallInst { - IntrinsicInst(); // DO NOT IMPLEMENT - IntrinsicInst(const IntrinsicInst&); // DO NOT IMPLEMENT - void operator=(const IntrinsicInst&); // DO NOT IMPLEMENT + IntrinsicInst() LLVM_DELETED_FUNCTION; + IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION; + void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION; public: /// getIntrinsicID - Return the intrinsic ID of this intrinsic. /// @@ -45,24 +45,22 @@ namespace llvm { } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const IntrinsicInst *) { return true; } static inline bool classof(const CallInst *I) { if (const Function *CF = I->getCalledFunction()) - return CF->getIntrinsicID() != 0; + return CF->isIntrinsic(); return false; } static inline bool classof(const Value *V) { return isa<CallInst>(V) && classof(cast<CallInst>(V)); } }; - + /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics /// class DbgInfoIntrinsic : public IntrinsicInst { public: // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const DbgInfoIntrinsic *) { return true; } static inline bool classof(const IntrinsicInst *I) { switch (I->getIntrinsicID()) { case Intrinsic::dbg_declare: @@ -86,7 +84,6 @@ namespace llvm { MDNode *getVariable() const { return cast<MDNode>(getArgOperand(1)); } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const DbgDeclareInst *) { return true; } static inline bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::dbg_declare; } @@ -108,7 +105,6 @@ namespace llvm { MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const DbgValueInst *) { return true; } static inline bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::dbg_value; } @@ -175,7 +171,6 @@ namespace llvm { } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MemIntrinsic *) { return true; } static inline bool classof(const IntrinsicInst *I) { switch (I->getIntrinsicID()) { case Intrinsic::memcpy: @@ -205,7 +200,6 @@ namespace llvm { } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MemSetInst *) { return true; } static inline bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::memset; } @@ -238,7 +232,6 @@ namespace llvm { } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MemTransferInst *) { return true; } static inline bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::memcpy || I->getIntrinsicID() == Intrinsic::memmove; @@ -254,7 +247,6 @@ namespace llvm { class MemCpyInst : public MemTransferInst { public: // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MemCpyInst *) { return true; } static inline bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::memcpy; } @@ -268,7 +260,6 @@ namespace llvm { class MemMoveInst : public MemTransferInst { public: // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MemMoveInst *) { return true; } static inline bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::memmove; } @@ -277,6 +268,49 @@ namespace llvm { } }; + /// VAStartInst - This represents the llvm.va_start intrinsic. + /// + class VAStartInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::vastart; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); } + }; + + /// VAEndInst - This represents the llvm.va_end intrinsic. + /// + class VAEndInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::vaend; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); } + }; + + /// VACopyInst - This represents the llvm.va_copy intrinsic. + /// + class VACopyInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::vacopy; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + Value *getDest() const { return const_cast<Value*>(getArgOperand(0)); } + Value *getSrc() const { return const_cast<Value*>(getArgOperand(1)); } + }; + } #endif diff --git a/include/llvm/Intrinsics.h b/include/llvm/IR/Intrinsics.h index c350388..1e20fd7 100644 --- a/include/llvm/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -26,7 +26,7 @@ class FunctionType; class Function; class LLVMContext; class Module; -class AttrListPtr; +class AttributeSet; /// Intrinsic Namespace - This namespace contains an enum with a value for /// every intrinsic/builtin function known by LLVM. These enum values are @@ -38,7 +38,7 @@ namespace Intrinsic { // Get the intrinsic enums generated from Intrinsics.td #define GET_INTRINSIC_ENUM_VALUES -#include "llvm/Intrinsics.gen" +#include "llvm/IR/Intrinsics.gen" #undef GET_INTRINSIC_ENUM_VALUES , num_intrinsics }; @@ -50,7 +50,7 @@ namespace Intrinsic { /// Intrinsic::getType(ID) - Return the function type for an intrinsic. /// FunctionType *getType(LLVMContext &Context, ID id, - ArrayRef<Type*> Tys = ArrayRef<Type*>()); + ArrayRef<Type*> Tys = ArrayRef<Type*>()); /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be /// overloaded. @@ -58,7 +58,7 @@ namespace Intrinsic { /// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic. /// - AttrListPtr getAttributes(ID id); + AttributeSet getAttributes(LLVMContext &C, ID id); /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function /// declaration for an intrinsic, and return it. diff --git a/include/llvm/Intrinsics.td b/include/llvm/IR/Intrinsics.td index d1a0fee..e9fbba9 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -121,15 +121,27 @@ def llvm_metadata_ty : LLVMType<MetadataVT>; // !{...} def llvm_x86mmx_ty : LLVMType<x86mmx>; def llvm_ptrx86mmx_ty : LLVMPointerType<llvm_x86mmx_ty>; // <1 x i64>* +def llvm_v2i1_ty : LLVMType<v2i1>; // 2 x i1 +def llvm_v4i1_ty : LLVMType<v4i1>; // 4 x i1 +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_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 def llvm_v16i8_ty : LLVMType<v16i8>; // 16 x i8 def llvm_v32i8_ty : LLVMType<v32i8>; // 32 x i8 +def llvm_v64i8_ty : LLVMType<v64i8>; // 64 x i8 + +def llvm_v1i16_ty : LLVMType<v1i16>; // 1 x i16 def llvm_v2i16_ty : LLVMType<v2i16>; // 2 x i16 def llvm_v4i16_ty : LLVMType<v4i16>; // 4 x i16 def llvm_v8i16_ty : LLVMType<v8i16>; // 8 x i16 def llvm_v16i16_ty : LLVMType<v16i16>; // 16 x i16 +def llvm_v32i16_ty : LLVMType<v32i16>; // 32 x i16 + +def llvm_v1i32_ty : LLVMType<v1i32>; // 1 x i32 def llvm_v2i32_ty : LLVMType<v2i32>; // 2 x i32 def llvm_v4i32_ty : LLVMType<v4i32>; // 4 x i32 def llvm_v8i32_ty : LLVMType<v8i32>; // 8 x i32 @@ -143,8 +155,10 @@ def llvm_v16i64_ty : LLVMType<v16i64>; // 16 x i64 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_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 def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here @@ -265,6 +279,10 @@ let Properties = [IntrReadMem] in { def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_fabs : Intrinsic<[llvm_anyfloat_ty], [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>]>; } let Properties = [IntrNoMem] in { @@ -279,9 +297,9 @@ let Properties = [IntrNoMem] in { // NOTE: these are internal interfaces. def int_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; -def int_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>; +def int_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>; -def int_siglongjmp : Intrinsic<[], [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], @@ -339,7 +357,7 @@ let Properties = [IntrNoMem] in { } def int_eh_sjlj_functioncontext : Intrinsic<[], [llvm_ptr_ty]>; def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; -def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>; +def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty], [IntrNoReturn]>; //===---------------- Generic Variable Attribute Intrinsics----------------===// // @@ -455,11 +473,11 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], // Target-specific intrinsics //===----------------------------------------------------------------------===// -include "llvm/IntrinsicsPowerPC.td" -include "llvm/IntrinsicsX86.td" -include "llvm/IntrinsicsARM.td" -include "llvm/IntrinsicsCellSPU.td" -include "llvm/IntrinsicsXCore.td" -include "llvm/IntrinsicsHexagon.td" -include "llvm/IntrinsicsNVVM.td" -include "llvm/IntrinsicsMips.td" +include "llvm/IR/IntrinsicsPowerPC.td" +include "llvm/IR/IntrinsicsX86.td" +include "llvm/IR/IntrinsicsARM.td" +include "llvm/IR/IntrinsicsXCore.td" +include "llvm/IR/IntrinsicsHexagon.td" +include "llvm/IR/IntrinsicsNVVM.td" +include "llvm/IR/IntrinsicsMips.td" +include "llvm/IR/IntrinsicsR600.td" diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td new file mode 100644 index 0000000..93b1ae1 --- /dev/null +++ b/include/llvm/IR/IntrinsicsARM.td @@ -0,0 +1,429 @@ +//===- IntrinsicsARM.td - Defines ARM intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the ARM-specific intrinsics. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// TLS + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + +def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, + Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Saturating Arithmentic + +def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; +def int_arm_qsub : GCCBuiltin<"__builtin_arm_qsub">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_arm_ssat : GCCBuiltin<"__builtin_arm_ssat">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Load and Store exclusive doubleword + +def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; +def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty], + [IntrReadArgMem]>; + +//===----------------------------------------------------------------------===// +// VFP + +def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; +def int_arm_set_fpscr : GCCBuiltin<"__builtin_arm_set_fpscr">, + Intrinsic<[], [llvm_i32_ty], []>; +def int_arm_vcvtr : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], + [IntrNoMem]>; +def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], + [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Coprocessor + +// Move to coprocessor +def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + +// Move from coprocessor +def int_arm_mrc : GCCBuiltin<"__builtin_arm_mrc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_mrc2 : GCCBuiltin<"__builtin_arm_mrc2">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; + +// Coprocessor data processing +def int_arm_cdp : GCCBuiltin<"__builtin_arm_cdp">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_cdp2 : GCCBuiltin<"__builtin_arm_cdp2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + +// Move from two registers to coprocessor +def int_arm_mcrr : GCCBuiltin<"__builtin_arm_mcrr">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) + +// The following classes do not correspond directly to GCC builtins. +class Neon_1Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; +class Neon_1Arg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>], [IntrNoMem]>; +class Neon_2Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +class Neon_2Arg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>, + LLVMExtendedElementVectorType<0>], + [IntrNoMem]>; +class Neon_2Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMTruncatedElementVectorType<0>, + LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; +class Neon_3Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +class Neon_3Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, + LLVMTruncatedElementVectorType<0>, + LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; +class Neon_CvtFxToFP_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; +class Neon_CvtFPToFx_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + +// The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. +// Besides the table, VTBL has one other v8i8 argument and VTBX has two. +// Overall, the classes range from 2 to 6 v8i8 arguments. +class Neon_Tbl2Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; +class Neon_Tbl3Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; +class Neon_Tbl4Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], + [IntrNoMem]>; +class Neon_Tbl5Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; +class Neon_Tbl6Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; + +// Arithmetic ops + +let Properties = [IntrNoMem, Commutative] in { + + // Vector Add. + def int_arm_neon_vhadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vhaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vrhadds : Neon_2Arg_Intrinsic; + 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. + def int_arm_neon_vmulp : Neon_2Arg_Intrinsic; + def int_arm_neon_vqdmulh : Neon_2Arg_Intrinsic; + def int_arm_neon_vqrdmulh : Neon_2Arg_Intrinsic; + def int_arm_neon_vmulls : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vmullu : Neon_2Arg_Long_Intrinsic; + 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; + + // Vector Minimum. + def int_arm_neon_vmins : Neon_2Arg_Intrinsic; + def int_arm_neon_vminu : Neon_2Arg_Intrinsic; + + // Vector Reciprocal Step. + def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; + + // Vector Reciprocal Square Root Step. + def int_arm_neon_vrsqrts : Neon_2Arg_Intrinsic; +} + +// Vector Subtract. +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. +def int_arm_neon_vacged : Intrinsic<[llvm_v2i32_ty], + [llvm_v2f32_ty, llvm_v2f32_ty], + [IntrNoMem]>; +def int_arm_neon_vacgeq : Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +def int_arm_neon_vacgtd : Intrinsic<[llvm_v2i32_ty], + [llvm_v2f32_ty, llvm_v2f32_ty], + [IntrNoMem]>; +def int_arm_neon_vacgtq : Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +// Vector Absolute Differences. +def int_arm_neon_vabds : Neon_2Arg_Intrinsic; +def int_arm_neon_vabdu : Neon_2Arg_Intrinsic; + +// Vector Pairwise Add. +def int_arm_neon_vpadd : Neon_2Arg_Intrinsic; + +// Vector Pairwise Add Long. +// Note: This is different than the other "long" NEON intrinsics because +// the result vector has half as many elements as the source vector. +// The source and destination vector types must be specified separately. +def int_arm_neon_vpaddls : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], + [IntrNoMem]>; +def int_arm_neon_vpaddlu : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], + [IntrNoMem]>; + +// Vector Pairwise Add and Accumulate Long. +// Note: This is similar to vpaddl but the destination vector also appears +// as the first argument. +def int_arm_neon_vpadals : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; +def int_arm_neon_vpadalu : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; + +// Vector Pairwise Maximum and Minimum. +def int_arm_neon_vpmaxs : Neon_2Arg_Intrinsic; +def int_arm_neon_vpmaxu : Neon_2Arg_Intrinsic; +def int_arm_neon_vpmins : Neon_2Arg_Intrinsic; +def int_arm_neon_vpminu : Neon_2Arg_Intrinsic; + +// Vector Shifts: +// +// The various saturating and rounding vector shift operations need to be +// represented by intrinsics in LLVM, and even the basic VSHL variable shift +// operation cannot be safely translated to LLVM's shift operators. VSHL can +// be used for both left and right shifts, or even combinations of the two, +// depending on the signs of the shift amounts. It also has well-defined +// behavior for shift amounts that LLVM leaves undefined. Only basic shifts +// by constants can be represented with LLVM's shift operators. +// +// The shift counts for these intrinsics are always vectors, even for constant +// shifts, where the constant is replicated. For consistency with VSHL (and +// other variable shift instructions), left shifts have positive shift counts +// and right shifts have negative shift counts. This convention is also used +// for constant right shift intrinsics, and to help preserve sanity, the +// intrinsic names use "shift" instead of either "shl" or "shr". Where +// applicable, signed and unsigned versions of the intrinsics are +// distinguished with "s" and "u" suffixes. A few NEON shift instructions, +// such as VQSHLU, take signed operands but produce unsigned results; these +// use a "su" suffix. + +// Vector Shift. +def int_arm_neon_vshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vshiftls : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vshiftlu : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vshiftn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Rounding Shift. +def int_arm_neon_vrshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vrshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vrshiftn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Saturating Shift. +def int_arm_neon_vqshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftsu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftns : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqshiftnu : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqshiftnsu : Neon_2Arg_Narrow_Intrinsic; + +// Vector Saturating Rounding Shift. +def int_arm_neon_vqrshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vqrshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqrshiftns : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqrshiftnu : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqrshiftnsu : Neon_2Arg_Narrow_Intrinsic; + +// Vector Shift and Insert. +def int_arm_neon_vshiftins : Neon_3Arg_Intrinsic; + +// Vector Absolute Value and Saturating Absolute Value. +def int_arm_neon_vabs : Neon_1Arg_Intrinsic; +def int_arm_neon_vqabs : Neon_1Arg_Intrinsic; + +// Vector Saturating Negate. +def int_arm_neon_vqneg : Neon_1Arg_Intrinsic; + +// Vector Count Leading Sign/Zero Bits. +def int_arm_neon_vcls : Neon_1Arg_Intrinsic; +def int_arm_neon_vclz : Neon_1Arg_Intrinsic; + +// Vector Count One Bits. +def int_arm_neon_vcnt : Neon_1Arg_Intrinsic; + +// Vector Reciprocal Estimate. +def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; + +// Vector Reciprocal Square Root Estimate. +def int_arm_neon_vrsqrte : Neon_1Arg_Intrinsic; + +// Vector Conversions Between Floating-point and Fixed-point. +def int_arm_neon_vcvtfp2fxs : Neon_CvtFPToFx_Intrinsic; +def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; +def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic; +def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic; + +// Vector Conversions Between Half-Precision and Single-Precision. +def int_arm_neon_vcvtfp2hf + : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_arm_neon_vcvthf2fp + : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; + +// Narrowing Saturating Vector Moves. +def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovnsu : Neon_1Arg_Narrow_Intrinsic; + +// Vector Table Lookup. +// The first 1-4 arguments are the table. +def int_arm_neon_vtbl1 : Neon_Tbl2Arg_Intrinsic; +def int_arm_neon_vtbl2 : Neon_Tbl3Arg_Intrinsic; +def int_arm_neon_vtbl3 : Neon_Tbl4Arg_Intrinsic; +def int_arm_neon_vtbl4 : Neon_Tbl5Arg_Intrinsic; + +// 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_arm_neon_vtbx1 : Neon_Tbl3Arg_Intrinsic; +def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; +def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; +def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; + +// De-interleaving vector loads from N-element structures. +// Source operands are the address and alignment. +def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_arm_neon_vld2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_arm_neon_vld3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + +// Vector load N-element structure to one lane. +// Source operands are: the address, the N input vectors (since only one +// lane is assigned), the lane number, and the alignment. +def int_arm_neon_vld2lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadArgMem]>; +def int_arm_neon_vld3lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadArgMem]>; + +// Interleaving vector stores from N-element structures. +// Source operands are: the address, the N vectors, and the alignment. +def int_arm_neon_vst1 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_arm_neon_vst2 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_arm_neon_vst3 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_arm_neon_vst4 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +// Vector store N-element structure from one lane. +// Source operands are: the address, the N vectors, the lane number, and +// the alignment. +def int_arm_neon_vst2lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_arm_neon_vst3lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_arm_neon_vst4lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; + +// Vector bitwise select. +def int_arm_neon_vbsl : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +} // end TargetPrefix diff --git a/include/llvm/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index 8a88729..8a88729 100644 --- a/include/llvm/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td diff --git a/include/llvm/IntrinsicsMips.td b/include/llvm/IR/IntrinsicsMips.td index e40e162..e40e162 100644 --- a/include/llvm/IntrinsicsMips.td +++ b/include/llvm/IR/IntrinsicsMips.td diff --git a/include/llvm/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index 1853c99..1853c99 100644 --- a/include/llvm/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td diff --git a/include/llvm/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index da85bfb..cde39cc 100644 --- a/include/llvm/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -22,7 +22,8 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_dcbf : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbi : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>; - def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td new file mode 100644 index 0000000..ecb5668 --- /dev/null +++ b/include/llvm/IR/IntrinsicsR600.td @@ -0,0 +1,36 @@ +//===- IntrinsicsR600.td - Defines R600 intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the R600-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "r600" in { + +class R600ReadPreloadRegisterIntrinsic<string name> + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<name>; + +multiclass R600ReadPreloadRegisterIntrinsic_xyz<string prefix> { + def _x : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_x")>; + def _y : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_y")>; + def _z : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_z")>; +} + +defm int_r600_read_global_size : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_global_size">; +defm int_r600_read_local_size : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_local_size">; +defm int_r600_read_ngroups : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_ngroups">; +defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_tgid">; +defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_tidig">; +} // End TargetPrefix = "r600" diff --git a/include/llvm/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 5ff0856..d2463c0 100644 --- a/include/llvm/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -2559,3 +2559,15 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_rdrand_32 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [], []>; def int_x86_rdrand_64 : Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; } + +//===----------------------------------------------------------------------===// +// RTM intrinsics. Transactional Memory support. + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_xbegin : GCCBuiltin<"__builtin_ia32_xbegin">, + Intrinsic<[llvm_i32_ty], [], []>; + def int_x86_xend : GCCBuiltin<"__builtin_ia32_xend">, + Intrinsic<[], [], []>; + def int_x86_xabort : GCCBuiltin<"__builtin_ia32_xabort">, + Intrinsic<[], [llvm_i8_ty], [IntrNoReturn]>; +} diff --git a/include/llvm/IntrinsicsXCore.td b/include/llvm/IR/IntrinsicsXCore.td index a481313..a481313 100644 --- a/include/llvm/IntrinsicsXCore.td +++ b/include/llvm/IR/IntrinsicsXCore.td diff --git a/include/llvm/LLVMContext.h b/include/llvm/IR/LLVMContext.h index a8306a9..58fb39f 100644 --- a/include/llvm/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -15,6 +15,8 @@ #ifndef LLVM_LLVMCONTEXT_H #define LLVM_LLVMCONTEXT_H +#include "llvm/Support/Compiler.h" + namespace llvm { class LLVMContextImpl; @@ -43,7 +45,8 @@ public: MD_tbaa = 1, // "tbaa" MD_prof = 2, // "prof" MD_fpmath = 3, // "fpmath" - MD_range = 4 // "range" + MD_range = 4, // "range" + MD_tbaa_struct = 5 // "tbaa.struct" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. @@ -55,27 +58,39 @@ public: void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; - typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, - unsigned LocCookie); + typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context, + unsigned LocCookie); - /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked - /// when problems with inline asm are detected by the backend. The first - /// argument is a function pointer and the second is a context pointer that - /// gets passed into the DiagHandler. + /// setDiagnosticHandler - This method sets a handler that is invoked + /// when problems are detected by the backend. The first argument is a + /// function pointer and the second is a context pointer that gets passed + /// into the DiagHandler. /// /// LLVMContext doesn't take ownership or interpret either of these /// pointers. - void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, - void *DiagContext = 0); + void setDiagnosticHandler(DiagHandlerTy DiagHandler, void *DiagContext = 0); - /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by - /// setInlineAsmDiagnosticHandler. - InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const; + /// getDiagnosticHandler - Return the diagnostic handler set by + /// setDiagnosticHandler. + DiagHandlerTy getDiagnosticHandler() const; - /// getInlineAsmDiagnosticContext - Return the diagnostic context set by - /// setInlineAsmDiagnosticHandler. - void *getInlineAsmDiagnosticContext() const; + /// getDiagnosticContext - Return the diagnostic context set by + /// setDiagnosticHandler. + void *getDiagnosticContext() const; + /// FIXME: Temporary copies of the old names; to be removed as soon as + /// clang switches to the new ones. + typedef DiagHandlerTy InlineAsmDiagHandlerTy; + void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, + void *DiagContext = 0) { + setDiagnosticHandler(DiagHandler, DiagContext); + } + InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const { + return getDiagnosticHandler(); + } + void *getInlineAsmDiagnosticContext() const { + return getDiagnosticContext(); + } /// emitError - Emit an error message to the currently installed error handler /// with optional location information. This function returns, so code should @@ -86,10 +101,15 @@ public: void emitError(const Instruction *I, const Twine &ErrorStr); void emitError(const Twine &ErrorStr); + /// emitWarning - This is similar to emitError but it emits a warning instead + /// of an error. + void emitWarning(unsigned LocCookie, const Twine &ErrorStr); + void emitWarning(const Instruction *I, const Twine &ErrorStr); + void emitWarning(const Twine &ErrorStr); + private: - // DO NOT IMPLEMENT - LLVMContext(LLVMContext&); - void operator=(LLVMContext&); + LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; + void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; /// addModule - Register a module as being instantiated in this context. If /// the context is deleted, the module will be deleted as well. diff --git a/include/llvm/MDBuilder.h b/include/llvm/IR/MDBuilder.h index 2aa48b0..d3ca644 100644 --- a/include/llvm/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -15,11 +15,11 @@ #ifndef LLVM_MDBUILDER_H #define LLVM_MDBUILDER_H -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" -#include "llvm/Metadata.h" #include "llvm/ADT/APInt.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" namespace llvm { @@ -134,6 +134,27 @@ namespace llvm { } } + struct TBAAStructField { + uint64_t Offset; + uint64_t Size; + MDNode *TBAA; + TBAAStructField(uint64_t Offset, uint64_t Size, MDNode *TBAA) : + Offset(Offset), Size(Size), TBAA(TBAA) {} + }; + + /// \brief Return metadata for a tbaa.struct node with the given + /// struct field descriptions. + MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields) { + SmallVector<Value *, 4> Vals(Fields.size() * 3); + Type *Int64 = IntegerType::get(Context, 64); + for (unsigned i = 0, e = Fields.size(); i != e; ++i) { + Vals[i * 3 + 0] = ConstantInt::get(Int64, Fields[i].Offset); + Vals[i * 3 + 1] = ConstantInt::get(Int64, Fields[i].Size); + Vals[i * 3 + 2] = Fields[i].TBAA; + } + return MDNode::get(Context, Vals); + } + }; } // end namespace llvm diff --git a/include/llvm/Metadata.h b/include/llvm/IR/Metadata.h index b40549b..402abb3 100644 --- a/include/llvm/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -16,10 +16,10 @@ #ifndef LLVM_METADATA_H #define LLVM_METADATA_H -#include "llvm/Value.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Value.h" namespace llvm { class Constant; @@ -37,7 +37,7 @@ template<typename ValueSubClass, typename ItemParentClass> /// MDString is always unnamed. class MDString : public Value { virtual void anchor(); - MDString(const MDString &); // DO NOT IMPLEMENT + MDString(const MDString &) LLVM_DELETED_FUNCTION; explicit MDString(LLVMContext &C); public: @@ -59,7 +59,6 @@ public: iterator end() const { return getName().end(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MDString *) { return true; } static bool classof(const Value *V) { return V->getValueID() == MDStringVal; } @@ -71,8 +70,8 @@ class MDNodeOperand; //===----------------------------------------------------------------------===// /// MDNode - a tuple of other values. class MDNode : public Value, public FoldingSetNode { - MDNode(const MDNode &); // DO NOT IMPLEMENT - void operator=(const MDNode &); // DO NOT IMPLEMENT + MDNode(const MDNode &) LLVM_DELETED_FUNCTION; + void operator=(const MDNode &) LLVM_DELETED_FUNCTION; friend class MDNodeOperand; friend class LLVMContextImpl; friend struct FoldingSetTrait<MDNode>; @@ -161,7 +160,6 @@ public: void Profile(FoldingSetNodeID &ID) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MDNode *) { return true; } static bool classof(const Value *V) { return V->getValueID() == MDNodeVal; } @@ -195,7 +193,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> { friend struct ilist_traits<NamedMDNode>; friend class LLVMContextImpl; friend class Module; - NamedMDNode(const NamedMDNode &); // DO NOT IMPLEMENT + NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION; std::string Name; Module *Parent; diff --git a/include/llvm/Module.h b/include/llvm/IR/Module.h index e6303ac..4e1ca43 100644 --- a/include/llvm/Module.h +++ b/include/llvm/IR/Module.h @@ -15,13 +15,12 @@ #ifndef LLVM_MODULE_H #define LLVM_MODULE_H -#include "llvm/Function.h" -#include "llvm/GlobalVariable.h" -#include "llvm/GlobalAlias.h" -#include "llvm/Metadata.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/DataTypes.h" -#include <vector> namespace llvm { @@ -122,9 +121,6 @@ public: /// The type for the list of named metadata. typedef ilist<NamedMDNode> NamedMDListType; - /// The type for the list of dependent libraries. - typedef std::vector<std::string> LibraryListType; - /// The Global Variable iterator. typedef GlobalListType::iterator global_iterator; /// The Global Variable constant iterator. @@ -144,8 +140,6 @@ public: typedef NamedMDListType::iterator named_metadata_iterator; /// The named metadata constant interators. typedef NamedMDListType::const_iterator const_named_metadata_iterator; - /// The Library list iterator. - typedef LibraryListType::const_iterator lib_iterator; /// An enumeration for describing the endianess of the target machine. enum Endianness { AnyEndianness, LittleEndian, BigEndian }; @@ -195,7 +189,6 @@ private: GlobalListType GlobalList; ///< The Global Variables in the module FunctionListType FunctionList; ///< The Functions in the module AliasListType AliasList; ///< The Aliases in the module - LibraryListType LibraryList; ///< The Libraries needed by the module NamedMDListType NamedMDList; ///< The named metadata in the module std::string GlobalScopeAsm; ///< Inline Asm at global scope. ValueSymbolTable *ValSymTab; ///< Symbol table for values @@ -319,7 +312,7 @@ public: /// 4. Finally, the function exists but has the wrong prototype: return the /// function with a constantexpr cast to the right prototype. Constant *getOrInsertFunction(StringRef Name, FunctionType *T, - AttrListPtr AttributeList); + AttributeSet AttributeList); Constant *getOrInsertFunction(StringRef Name, FunctionType *T); @@ -331,7 +324,7 @@ public: /// null terminated list of function arguments, which makes it easier for /// clients to use. Constant *getOrInsertFunction(StringRef Name, - AttrListPtr AttributeList, + AttributeSet AttributeList, Type *RetTy, ...) END_WITH_NULL; /// getOrInsertFunction - Same as above, but without the attributes. @@ -340,7 +333,7 @@ public: Constant *getOrInsertTargetIntrinsic(StringRef Name, FunctionType *Ty, - AttrListPtr AttributeList); + AttributeSet AttributeList); /// getFunction - Look up the specified function in the module symbol table. /// If it does not exist, return null. @@ -527,23 +520,6 @@ public: bool empty() const { return FunctionList.empty(); } /// @} -/// @name Dependent Library Iteration -/// @{ - - /// @brief Get a constant iterator to beginning of dependent library list. - inline lib_iterator lib_begin() const { return LibraryList.begin(); } - /// @brief Get a constant iterator to end of dependent library list. - inline lib_iterator lib_end() const { return LibraryList.end(); } - /// @brief Returns the number of items in the list of libraries. - inline size_t lib_size() const { return LibraryList.size(); } - /// @brief Add a library to the list of dependent libraries - void addLibrary(StringRef Lib); - /// @brief Remove a library from the list of dependent libraries - void removeLibrary(StringRef Lib); - /// @brief Get all the libraries - inline const LibraryListType& getLibraries() const { return LibraryList; } - -/// @} /// @name Alias Iteration /// @{ diff --git a/include/llvm/OperandTraits.h b/include/llvm/IR/OperandTraits.h index 3d8dc32..60c8b09 100644 --- a/include/llvm/OperandTraits.h +++ b/include/llvm/IR/OperandTraits.h @@ -15,7 +15,7 @@ #ifndef LLVM_OPERAND_TRAITS_H #define LLVM_OPERAND_TRAITS_H -#include "llvm/User.h" +#include "llvm/IR/User.h" namespace llvm { diff --git a/include/llvm/Operator.h b/include/llvm/IR/Operator.h index 1e86980..577b41a 100644 --- a/include/llvm/Operator.h +++ b/include/llvm/IR/Operator.h @@ -15,9 +15,12 @@ #ifndef LLVM_OPERATOR_H #define LLVM_OPERATOR_H -#include "llvm/Constants.h" -#include "llvm/Instruction.h" -#include "llvm/Type.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" namespace llvm { @@ -32,9 +35,14 @@ class Operator : public User { private: // Do not implement any of these. The Operator class is intended to be used // as a utility, and is never itself instantiated. - void *operator new(size_t, unsigned); - void *operator new(size_t s); - Operator(); + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t s) LLVM_DELETED_FUNCTION; + Operator() LLVM_DELETED_FUNCTION; + +protected: + // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete + // an overridden method that's not deleted in the base class. Cannot leave + // this unimplemented because that leads to an ODR-violation. ~Operator(); public: @@ -57,7 +65,6 @@ public: return Instruction::UserOp1; } - static inline bool classof(const Operator *) { return true; } static inline bool classof(const Instruction *) { return true; } static inline bool classof(const ConstantExpr *) { return true; } static inline bool classof(const Value *V) { @@ -77,8 +84,6 @@ public: }; private: - ~OverflowingBinaryOperator(); // do not implement - friend class BinaryOperator; friend class ConstantExpr; void setHasNoUnsignedWrap(bool B) { @@ -103,7 +108,6 @@ public: return (SubclassOptionalData & NoSignedWrap) != 0; } - static inline bool classof(const OverflowingBinaryOperator *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Add || I->getOpcode() == Instruction::Sub || @@ -129,23 +133,21 @@ public: enum { IsExact = (1 << 0) }; - -private: - ~PossiblyExactOperator(); // do not implement +private: friend class BinaryOperator; friend class ConstantExpr; void setIsExact(bool B) { SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); } - + public: /// isExact - Test whether this division is known to be exact, with /// zero remainder. bool isExact() const { return SubclassOptionalData & IsExact; } - + static bool isPossiblyExactOpcode(unsigned OpC) { return OpC == Instruction::SDiv || OpC == Instruction::UDiv || @@ -164,20 +166,139 @@ public: } }; +/// Convenience struct for specifying and reasoning about fast-math flags. +class FastMathFlags { +private: + friend class FPMathOperator; + unsigned Flags; + FastMathFlags(unsigned F) : Flags(F) { } + +public: + enum { + UnsafeAlgebra = (1 << 0), + NoNaNs = (1 << 1), + NoInfs = (1 << 2), + NoSignedZeros = (1 << 3), + AllowReciprocal = (1 << 4) + }; + + FastMathFlags() : Flags(0) + { } + + /// Whether any flag is set + bool any() { return Flags != 0; } + + /// Set all the flags to false + void clear() { Flags = 0; } + + /// Flag queries + bool noNaNs() { return 0 != (Flags & NoNaNs); } + bool noInfs() { return 0 != (Flags & NoInfs); } + bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); } + bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); } + bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); } + + /// Flag setters + void setNoNaNs() { Flags |= NoNaNs; } + void setNoInfs() { Flags |= NoInfs; } + void setNoSignedZeros() { Flags |= NoSignedZeros; } + void setAllowReciprocal() { Flags |= AllowReciprocal; } + void setUnsafeAlgebra() { + Flags |= UnsafeAlgebra; + setNoNaNs(); + setNoInfs(); + setNoSignedZeros(); + setAllowReciprocal(); + } +}; + + /// FPMathOperator - Utility class for floating point operations which can have /// information about relaxed accuracy requirements attached to them. class FPMathOperator : public Operator { private: - ~FPMathOperator(); // do not implement + friend class Instruction; + + void setHasUnsafeAlgebra(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::UnsafeAlgebra) | + (B * FastMathFlags::UnsafeAlgebra); + + // Unsafe algebra implies all the others + if (B) { + setHasNoNaNs(true); + setHasNoInfs(true); + setHasNoSignedZeros(true); + setHasAllowReciprocal(true); + } + } + void setHasNoNaNs(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::NoNaNs) | + (B * FastMathFlags::NoNaNs); + } + void setHasNoInfs(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::NoInfs) | + (B * FastMathFlags::NoInfs); + } + void setHasNoSignedZeros(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) | + (B * FastMathFlags::NoSignedZeros); + } + void setHasAllowReciprocal(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | + (B * FastMathFlags::AllowReciprocal); + } + + /// Convenience function for setting all the fast-math flags + void setFastMathFlags(FastMathFlags FMF) { + SubclassOptionalData |= FMF.Flags; + } public: + /// Test whether this operation is permitted to be + /// algebraically transformed, aka the 'A' fast-math property. + bool hasUnsafeAlgebra() const { + return (SubclassOptionalData & FastMathFlags::UnsafeAlgebra) != 0; + } + + /// Test whether this operation's arguments and results are to be + /// treated as non-NaN, aka the 'N' fast-math property. + bool hasNoNaNs() const { + return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0; + } + + /// Test whether this operation's arguments and results are to be + /// treated as NoN-Inf, aka the 'I' fast-math property. + bool hasNoInfs() const { + return (SubclassOptionalData & FastMathFlags::NoInfs) != 0; + } + + /// Test whether this operation can treat the sign of zero + /// as insignificant, aka the 'S' fast-math property. + bool hasNoSignedZeros() const { + return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0; + } + + /// Test whether this operation is permitted to use + /// reciprocal instead of division, aka the 'R' fast-math property. + bool hasAllowReciprocal() const { + return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; + } + + /// Convenience function for getting all the fast-math flags + FastMathFlags getFastMathFlags() const { + return FastMathFlags(SubclassOptionalData); + } /// \brief Get the maximum error permitted by this operation in ULPs. An /// accuracy of 0.0 means that the operation should be performed with the /// default precision. float getFPAccuracy() const; - static inline bool classof(const FPMathOperator *) { return true; } static inline bool classof(const Instruction *I) { return I->getType()->isFPOrFPVectorTy(); } @@ -186,16 +307,12 @@ public: } }; - + /// ConcreteOperator - A helper template for defining operators for individual /// opcodes. template<typename SuperClass, unsigned Opc> class ConcreteOperator : public SuperClass { - ~ConcreteOperator(); // DO NOT IMPLEMENT public: - static inline bool classof(const ConcreteOperator<SuperClass, Opc> *) { - return true; - } static inline bool classof(const Instruction *I) { return I->getOpcode() == Opc; } @@ -210,45 +327,35 @@ public: class AddOperator : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> { - ~AddOperator(); // DO NOT IMPLEMENT }; class SubOperator : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> { - ~SubOperator(); // DO NOT IMPLEMENT }; class MulOperator : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> { - ~MulOperator(); // DO NOT IMPLEMENT }; class ShlOperator : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> { - ~ShlOperator(); // DO NOT IMPLEMENT }; - + class SDivOperator : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> { - ~SDivOperator(); // DO NOT IMPLEMENT }; class UDivOperator : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> { - ~UDivOperator(); // DO NOT IMPLEMENT }; class AShrOperator : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> { - ~AShrOperator(); // DO NOT IMPLEMENT }; class LShrOperator : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> { - ~LShrOperator(); // DO NOT IMPLEMENT }; - - - + + + class GEPOperator : public ConcreteOperator<Operator, Instruction::GetElementPtr> { - ~GEPOperator(); // DO NOT IMPLEMENT - enum { IsInBounds = (1 << 0) }; @@ -288,6 +395,12 @@ public: return getPointerOperand()->getType(); } + /// getPointerAddressSpace - Method to return the address space of the + /// pointer operand. + unsigned getPointerAddressSpace() const { + return cast<PointerType>(getPointerOperandType())->getAddressSpace(); + } + unsigned getNumIndices() const { // Note: always non-negative return getNumOperands() - 1; } @@ -319,6 +432,45 @@ public: } return true; } + + /// \brief Accumulate the constant address offset of this GEP if possible. + /// + /// This routine accepts an APInt into which it will accumulate the constant + /// 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. + bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { + assert(Offset.getBitWidth() == + DL.getPointerSizeInBits(getPointerAddressSpace()) && + "The offset must have exactly as many bits as our pointer."); + + for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); + GTI != GTE; ++GTI) { + ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); + if (!OpC) + return false; + if (OpC->isZero()) + continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (StructType *STy = dyn_cast<StructType>(*GTI)) { + unsigned ElementIdx = OpC->getZExtValue(); + const StructLayout *SL = DL.getStructLayout(STy); + Offset += APInt(Offset.getBitWidth(), + SL->getElementOffset(ElementIdx)); + continue; + } + + // For array or vector indices, scale the index by the size of the type. + APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth()); + Offset += Index * APInt(Offset.getBitWidth(), + DL.getTypeAllocSize(GTI.getIndexedType())); + } + return true; + } + }; } // End llvm namespace diff --git a/include/llvm/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h index ec5c88f..ec5c88f 100644 --- a/include/llvm/SymbolTableListTraits.h +++ b/include/llvm/IR/SymbolTableListTraits.h diff --git a/include/llvm/Type.h b/include/llvm/IR/Type.h index 185258d..def4575 100644 --- a/include/llvm/Type.h +++ b/include/llvm/IR/Type.h @@ -153,7 +153,7 @@ public: /// isPPC_FP128Ty - Return true if this is powerpc long double. bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; } - /// isFloatingPointTy - Return true if this is one of the five floating point + /// isFloatingPointTy - Return true if this is one of the six floating point /// types bool isFloatingPointTy() const { return getTypeID() == HalfTyID || getTypeID() == FloatTyID || @@ -167,7 +167,7 @@ public: /// isFPOrFPVectorTy - Return true if this is a FP type or a vector of FP. /// - bool isFPOrFPVectorTy() const; + bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); } /// isLabelTy - Return true if this is 'label'. bool isLabelTy() const { return getTypeID() == LabelTyID; } @@ -185,7 +185,7 @@ public: /// isIntOrIntVectorTy - Return true if this is an integer type or a vector of /// integer types. /// - bool isIntOrIntVectorTy() const; + bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); } /// isFunctionTy - True if this is an instance of FunctionType. /// @@ -203,6 +203,11 @@ public: /// bool isPointerTy() const { return getTypeID() == PointerTyID; } + /// isPtrOrPtrVectorTy - Return true if this is a pointer type or a vector of + /// pointer types. + /// + bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); } + /// isVectorTy - True if this is an instance of VectorType. /// bool isVectorTy() const { return getTypeID() == VectorTyID; } @@ -252,7 +257,7 @@ public: /// isSized - Return true if it makes sense to take the size of this type. To /// get the actual size for a particular target, it is reasonable to use the - /// TargetData subsystem to do this. + /// DataLayout subsystem to do this. /// bool isSized() const { // If it's a primitive, it is always sized. @@ -276,7 +281,7 @@ public: /// /// Note that this may not reflect the size of memory allocated for an /// instance of the type or the number of bytes that are written when an - /// instance of the type is stored to memory. The TargetData class provides + /// instance of the type is stored to memory. The DataLayout class provides /// additional query functions to provide this information. /// unsigned getPrimitiveSizeInBits() const; @@ -293,6 +298,7 @@ public: /// getScalarType - If this is a vector type, return the element type, /// otherwise return 'this'. + const Type *getScalarType() const; Type *getScalarType(); //===--------------------------------------------------------------------===// @@ -340,8 +346,10 @@ public: unsigned getVectorNumElements() const; Type *getVectorElementType() const { return getSequentialElementType(); } - unsigned getPointerAddressSpace() const; Type *getPointerElementType() const { return getSequentialElementType(); } + + /// \brief Get the address space of this pointer or pointer vector type. + unsigned getPointerAddressSpace() const; //===--------------------------------------------------------------------===// // Static members exported by the Type class itself. Useful for getting @@ -389,9 +397,6 @@ public: static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0); static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0); - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Type *) { return true; } - /// getPointerTo - Return a pointer to the current type. This is equivalent /// to PointerType::get(Foo, AddrSpace). PointerType *getPointerTo(unsigned AddrSpace = 0); diff --git a/include/llvm/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h index 0b56479..83ca2a3 100644 --- a/include/llvm/TypeBuilder.h +++ b/include/llvm/IR/TypeBuilder.h @@ -15,8 +15,8 @@ #ifndef LLVM_TYPEBUILDER_H #define LLVM_TYPEBUILDER_H -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" #include <limits.h> namespace llvm { diff --git a/include/llvm/TypeFinder.h b/include/llvm/IR/TypeFinder.h index 5d80705..cea66a4 100644 --- a/include/llvm/TypeFinder.h +++ b/include/llvm/IR/TypeFinder.h @@ -1,4 +1,4 @@ -//===-- llvm/TypeFinder.h - Class for finding used struct types -*- C++ -*-===// +//===-- llvm/IR/TypeFinder.h - Class to find used struct types --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TYPEFINDER_H -#define LLVM_TYPEFINDER_H +#ifndef LLVM_IR_TYPEFINDER_H +#define LLVM_IR_TYPEFINDER_H #include "llvm/ADT/DenseSet.h" #include <vector> diff --git a/include/llvm/Use.h b/include/llvm/IR/Use.h index a496325..8080445 100644 --- a/include/llvm/Use.h +++ b/include/llvm/IR/Use.h @@ -26,6 +26,7 @@ #define LLVM_USE_H #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Compiler.h" #include <cstddef> #include <iterator> @@ -66,7 +67,7 @@ public: private: /// Copy ctor - do not implement - Use(const Use &U); + Use(const Use &U) LLVM_DELETED_FUNCTION; /// Destructor - Only for zap() ~Use() { diff --git a/include/llvm/User.h b/include/llvm/IR/User.h index 5d5460c..843d20b 100644 --- a/include/llvm/User.h +++ b/include/llvm/IR/User.h @@ -19,8 +19,8 @@ #ifndef LLVM_USER_H #define LLVM_USER_H +#include "llvm/IR/Value.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Value.h" namespace llvm { @@ -31,8 +31,8 @@ template <class> struct OperandTraits; class User : public Value { - User(const User &); // Do not implement - void *operator new(size_t); // Do not implement + User(const User &) LLVM_DELETED_FUNCTION; + void *operator new(size_t) LLVM_DELETED_FUNCTION; template <unsigned> friend struct HungoffOperandTraits; virtual void anchor(); @@ -104,7 +104,7 @@ public: assert(i < NumOperands && "getOperandUse() out of range!"); return OperandList[i]; } - + unsigned getNumOperands() const { return NumOperands; } // --------------------------------------------------------------------------- @@ -118,6 +118,45 @@ public: inline op_iterator op_end() { return OperandList+NumOperands; } inline const_op_iterator op_end() const { return OperandList+NumOperands; } + /// Convenience iterator for directly iterating over the Values in the + /// OperandList + class value_op_iterator : public std::iterator<std::forward_iterator_tag, + Value*> { + op_iterator OI; + public: + explicit value_op_iterator(Use *U) : OI(U) {} + + bool operator==(const value_op_iterator &x) const { + return OI == x.OI; + } + bool operator!=(const value_op_iterator &x) const { + return !operator==(x); + } + + /// Iterator traversal: forward iteration only + value_op_iterator &operator++() { // Preincrement + ++OI; + return *this; + } + value_op_iterator operator++(int) { // Postincrement + value_op_iterator tmp = *this; ++*this; return tmp; + } + + /// Retrieve a pointer to the current Value. + Value *operator*() const { + return *OI; + } + + Value *operator->() const { return operator*(); } + }; + + inline value_op_iterator value_op_begin() { + return value_op_iterator(op_begin()); + } + inline value_op_iterator value_op_end() { + return value_op_iterator(op_end()); + } + // dropAllReferences() - This function is in charge of "letting go" of all // objects that this User refers to. This allows one to // 'delete' a whole class at a time, even though there may be circular @@ -137,7 +176,6 @@ public: void replaceUsesOfWith(Value *From, Value *To); // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const User *) { return true; } static inline bool classof(const Value *V) { return isa<Instruction>(V) || isa<Constant>(V); } diff --git a/include/llvm/Value.h b/include/llvm/IR/Value.h index a82ac45..85fdfe3 100644 --- a/include/llvm/Value.h +++ b/include/llvm/IR/Value.h @@ -14,8 +14,9 @@ #ifndef LLVM_VALUE_H #define LLVM_VALUE_H -#include "llvm/Use.h" +#include "llvm/IR/Use.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" namespace llvm { @@ -80,8 +81,8 @@ private: friend class ValueHandleBase; ValueName *Name; - void operator=(const Value &); // Do not implement - Value(const Value &); // Do not implement + void operator=(const Value &) LLVM_DELETED_FUNCTION; + Value(const Value &) LLVM_DELETED_FUNCTION; protected: /// printCustom - Value subclasses can override this to implement custom @@ -120,7 +121,7 @@ public: /// setName() - Change the name of the value, choosing a new unique name if /// the provided name is taken. /// - /// \arg Name - The new name; or "" if the value's name should be removed. + /// \param Name The new name; or "" if the value's name should be removed. void setName(const Twine &Name); @@ -256,11 +257,6 @@ public: /// hasValueHandle - Return true if there is a value handle associated with /// this value. bool hasValueHandle() const { return HasValueHandle; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Value *) { - return true; // Values are always values. - } /// stripPointerCasts - This method strips off any unneeded pointer casts and /// all-zero GEPs from the specified value, returning the original uncasted diff --git a/include/llvm/ValueSymbolTable.h b/include/llvm/IR/ValueSymbolTable.h index 1738cc4..3ea095b 100644 --- a/include/llvm/ValueSymbolTable.h +++ b/include/llvm/IR/ValueSymbolTable.h @@ -14,8 +14,8 @@ #ifndef LLVM_VALUE_SYMBOL_TABLE_H #define LLVM_VALUE_SYMBOL_TABLE_H -#include "llvm/Value.h" #include "llvm/ADT/StringMap.h" +#include "llvm/IR/Value.h" #include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index bede4eb..79037f7 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -66,8 +66,10 @@ void initializeAliasDebuggerPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlwaysInlinerPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); +void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeBasicCallGraphPass(PassRegistry&); +void initializeBasicTTIPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); void initializeBlockPlacementPass(PassRegistry&); @@ -87,6 +89,7 @@ void initializeCodePlacementOptPass(PassRegistry&); void initializeConstantMergePass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&); void initializeMachineCopyPropagationPass(PassRegistry&); +void initializeCostModelAnalysisPass(PassRegistry&); void initializeCorrelatedValuePropagationPass(PassRegistry&); void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); @@ -94,6 +97,7 @@ void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); +void initializeDependenceAnalysisPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); void initializeDomPrinterPass(PassRegistry&); @@ -107,6 +111,8 @@ void initializeExpandPostRAPass(PassRegistry&); void initializePathProfilerPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); +void initializeAddressSanitizerModulePass(PassRegistry&); +void initializeMemorySanitizerPass(PassRegistry&); void initializeThreadSanitizerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); @@ -145,7 +151,6 @@ void initializeProfileMetadataLoaderPassPass(PassRegistry&); void initializePathProfileLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLoopDeletionPass(PassRegistry&); -void initializeLoopDependenceAnalysisPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); void initializeLoopInfoPass(PassRegistry&); void initializeLoopInstSimplifyPass(PassRegistry&); @@ -167,9 +172,9 @@ void initializeMachineBlockPlacementStatsPass(PassRegistry&); void initializeMachineBranchProbabilityInfoPass(PassRegistry&); void initializeMachineCSEPass(PassRegistry&); void initializeMachineDominatorTreePass(PassRegistry&); +void initializeMachinePostDominatorTreePass(PassRegistry&); void initializeMachineLICMPass(PassRegistry&); void initializeMachineLoopInfoPass(PassRegistry&); -void initializeMachineLoopRangesPass(PassRegistry&); void initializeMachineModuleInfoPass(PassRegistry&); void initializeMachineSchedulerPass(PassRegistry&); void initializeMachineSinkingPass(PassRegistry&); @@ -178,6 +183,7 @@ void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); void initializeMemoryDependenceAnalysisPass(PassRegistry&); +void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); void initializeNoAAPass(PassRegistry&); @@ -220,6 +226,7 @@ void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); +void initializeSROAPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); @@ -243,7 +250,9 @@ void initializeStrongPHIEliminationPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); -void initializeTargetDataPass(PassRegistry&); +void initializeDataLayoutPass(PassRegistry&); +void initializeTargetTransformInfoAnalysisGroup(PassRegistry&); +void initializeNoTTIPass(PassRegistry&); void initializeTargetLibraryInfoPass(PassRegistry&); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); @@ -256,6 +265,7 @@ void initializeVirtRegRewriterPass(PassRegistry&); void initializeInstSimplifierPass(PassRegistry&); void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); +void initializeLoopVectorizePass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); } diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/InstVisitor.h index 109b3cf..2911703 100644 --- a/include/llvm/Support/InstVisitor.h +++ b/include/llvm/InstVisitor.h @@ -1,4 +1,4 @@ -//===- llvm/Support/InstVisitor.h - Define instruction visitors -*- C++ -*-===// +//===- llvm/InstVisitor.h - Instruction visitor templates -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -8,14 +8,14 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_INSTVISITOR_H -#define LLVM_SUPPORT_INSTVISITOR_H +#ifndef LLVM_INSTVISITOR_H +#define LLVM_INSTVISITOR_H -#include "llvm/Function.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Module.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/ErrorHandling.h" @@ -25,7 +25,7 @@ namespace llvm { // types now... // #define HANDLE_INST(NUM, OPCODE, CLASS) class CLASS; -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" #define DELEGATE(CLASS_TO_VISIT) \ return static_cast<SubClass*>(this)-> \ @@ -123,7 +123,7 @@ public: case Instruction::OPCODE: return \ static_cast<SubClass*>(this)-> \ visit##OPCODE(static_cast<CLASS&>(I)); -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" } } @@ -158,7 +158,7 @@ public: else \ DELEGATE(CLASS); \ } -#include "llvm/Instruction.def" +#include "llvm/IR/Instruction.def" // Specific Instruction type classes... note that all of the casts are // necessary because we use the instruction classes as opaque types... @@ -209,6 +209,9 @@ public: RetTy visitMemMoveInst(MemMoveInst &I) { DELEGATE(MemTransferInst); } RetTy visitMemTransferInst(MemTransferInst &I) { DELEGATE(MemIntrinsic); } RetTy visitMemIntrinsic(MemIntrinsic &I) { DELEGATE(IntrinsicInst); } + RetTy visitVAStartInst(VAStartInst &I) { DELEGATE(IntrinsicInst); } + RetTy visitVAEndInst(VAEndInst &I) { DELEGATE(IntrinsicInst); } + RetTy visitVACopyInst(VACopyInst &I) { DELEGATE(IntrinsicInst); } RetTy visitIntrinsicInst(IntrinsicInst &I) { DELEGATE(CallInst); } // Call and Invoke are slightly different as they delegate first through @@ -262,6 +265,9 @@ private: case Intrinsic::memcpy: DELEGATE(MemCpyInst); case Intrinsic::memmove: DELEGATE(MemMoveInst); case Intrinsic::memset: DELEGATE(MemSetInst); + case Intrinsic::vastart: DELEGATE(VAStartInst); + case Intrinsic::vaend: DELEGATE(VAEndInst); + case Intrinsic::vacopy: DELEGATE(VACopyInst); case Intrinsic::not_intrinsic: break; } } diff --git a/include/llvm/IntrinsicsARM.td b/include/llvm/IntrinsicsARM.td deleted file mode 100644 index fa8034e..0000000 --- a/include/llvm/IntrinsicsARM.td +++ /dev/null @@ -1,442 +0,0 @@ -//===- IntrinsicsARM.td - Defines ARM intrinsics -----------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the ARM-specific intrinsics. -// -//===----------------------------------------------------------------------===// - - -//===----------------------------------------------------------------------===// -// TLS - -let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". - def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, - Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// Saturating Arithmentic - -let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". - def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, Commutative]>; - def int_arm_qsub : GCCBuiltin<"__builtin_arm_qsub">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_arm_ssat : GCCBuiltin<"__builtin_arm_ssat">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// Load and Store exclusive doubleword - -let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". - def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, - llvm_ptr_ty], [IntrReadWriteArgMem]>; - def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty], - [IntrReadArgMem]>; -} - -//===----------------------------------------------------------------------===// -// VFP - -let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". - def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">, - Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; - def int_arm_set_fpscr : GCCBuiltin<"__builtin_arm_set_fpscr">, - Intrinsic<[], [llvm_i32_ty], []>; - def int_arm_vcvtr : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], - [IntrNoMem]>; - def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], - [IntrNoMem]>; -} - -//===----------------------------------------------------------------------===// -// Coprocessor - -let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". - // Move to coprocessor - def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; - - // Move from coprocessor - def int_arm_mrc : GCCBuiltin<"__builtin_arm_mrc">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; - def int_arm_mrc2 : GCCBuiltin<"__builtin_arm_mrc2">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; - - // Coprocessor data processing - def int_arm_cdp : GCCBuiltin<"__builtin_arm_cdp">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; - def int_arm_cdp2 : GCCBuiltin<"__builtin_arm_cdp2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; - - // Move from two registers to coprocessor - def int_arm_mcrr : GCCBuiltin<"__builtin_arm_mcrr">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; - def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; -} - -//===----------------------------------------------------------------------===// -// Advanced SIMD (NEON) - -let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". - - // The following classes do not correspond directly to GCC builtins. - class Neon_1Arg_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; - class Neon_1Arg_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>], [IntrNoMem]>; - class Neon_2Arg_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - class Neon_2Arg_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>, - LLVMExtendedElementVectorType<0>], - [IntrNoMem]>; - class Neon_2Arg_Long_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMTruncatedElementVectorType<0>, - LLVMTruncatedElementVectorType<0>], - [IntrNoMem]>; - class Neon_3Arg_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - class Neon_3Arg_Long_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMTruncatedElementVectorType<0>, - LLVMTruncatedElementVectorType<0>], - [IntrNoMem]>; - class Neon_CvtFxToFP_Intrinsic - : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; - class Neon_CvtFPToFx_Intrinsic - : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; - - // The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. - // Besides the table, VTBL has one other v8i8 argument and VTBX has two. - // Overall, the classes range from 2 to 6 v8i8 arguments. - class Neon_Tbl2Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; - class Neon_Tbl3Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; - class Neon_Tbl4Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], - [IntrNoMem]>; - class Neon_Tbl5Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; - class Neon_Tbl6Arg_Intrinsic - : Intrinsic<[llvm_v8i8_ty], - [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; -} - -// Arithmetic ops - -let Properties = [IntrNoMem, Commutative] in { - - // Vector Add. - def int_arm_neon_vhadds : Neon_2Arg_Intrinsic; - def int_arm_neon_vhaddu : Neon_2Arg_Intrinsic; - def int_arm_neon_vrhadds : Neon_2Arg_Intrinsic; - 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. - def int_arm_neon_vmulp : Neon_2Arg_Intrinsic; - def int_arm_neon_vqdmulh : Neon_2Arg_Intrinsic; - def int_arm_neon_vqrdmulh : Neon_2Arg_Intrinsic; - def int_arm_neon_vmulls : Neon_2Arg_Long_Intrinsic; - def int_arm_neon_vmullu : Neon_2Arg_Long_Intrinsic; - 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; - - // Vector Minimum. - def int_arm_neon_vmins : Neon_2Arg_Intrinsic; - def int_arm_neon_vminu : Neon_2Arg_Intrinsic; - - // Vector Reciprocal Step. - def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; - - // Vector Reciprocal Square Root Step. - def int_arm_neon_vrsqrts : Neon_2Arg_Intrinsic; -} - -// Vector Subtract. -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. -let TargetPrefix = "arm" in { - def int_arm_neon_vacged : Intrinsic<[llvm_v2i32_ty], - [llvm_v2f32_ty, llvm_v2f32_ty], - [IntrNoMem]>; - def int_arm_neon_vacgeq : Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_arm_neon_vacgtd : Intrinsic<[llvm_v2i32_ty], - [llvm_v2f32_ty, llvm_v2f32_ty], - [IntrNoMem]>; - def int_arm_neon_vacgtq : Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; -} - -// Vector Absolute Differences. -def int_arm_neon_vabds : Neon_2Arg_Intrinsic; -def int_arm_neon_vabdu : Neon_2Arg_Intrinsic; - -// Vector Pairwise Add. -def int_arm_neon_vpadd : Neon_2Arg_Intrinsic; - -// Vector Pairwise Add Long. -// Note: This is different than the other "long" NEON intrinsics because -// the result vector has half as many elements as the source vector. -// The source and destination vector types must be specified separately. -let TargetPrefix = "arm" in { - def int_arm_neon_vpaddls : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], - [IntrNoMem]>; - def int_arm_neon_vpaddlu : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], - [IntrNoMem]>; -} - -// Vector Pairwise Add and Accumulate Long. -// Note: This is similar to vpaddl but the destination vector also appears -// as the first argument. -let TargetPrefix = "arm" in { - def int_arm_neon_vpadals : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty], - [IntrNoMem]>; - def int_arm_neon_vpadalu : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty], - [IntrNoMem]>; -} - -// Vector Pairwise Maximum and Minimum. -def int_arm_neon_vpmaxs : Neon_2Arg_Intrinsic; -def int_arm_neon_vpmaxu : Neon_2Arg_Intrinsic; -def int_arm_neon_vpmins : Neon_2Arg_Intrinsic; -def int_arm_neon_vpminu : Neon_2Arg_Intrinsic; - -// Vector Shifts: -// -// The various saturating and rounding vector shift operations need to be -// represented by intrinsics in LLVM, and even the basic VSHL variable shift -// operation cannot be safely translated to LLVM's shift operators. VSHL can -// be used for both left and right shifts, or even combinations of the two, -// depending on the signs of the shift amounts. It also has well-defined -// behavior for shift amounts that LLVM leaves undefined. Only basic shifts -// by constants can be represented with LLVM's shift operators. -// -// The shift counts for these intrinsics are always vectors, even for constant -// shifts, where the constant is replicated. For consistency with VSHL (and -// other variable shift instructions), left shifts have positive shift counts -// and right shifts have negative shift counts. This convention is also used -// for constant right shift intrinsics, and to help preserve sanity, the -// intrinsic names use "shift" instead of either "shl" or "shr". Where -// applicable, signed and unsigned versions of the intrinsics are -// distinguished with "s" and "u" suffixes. A few NEON shift instructions, -// such as VQSHLU, take signed operands but produce unsigned results; these -// use a "su" suffix. - -// Vector Shift. -def int_arm_neon_vshifts : Neon_2Arg_Intrinsic; -def int_arm_neon_vshiftu : Neon_2Arg_Intrinsic; -def int_arm_neon_vshiftls : Neon_2Arg_Long_Intrinsic; -def int_arm_neon_vshiftlu : Neon_2Arg_Long_Intrinsic; -def int_arm_neon_vshiftn : Neon_2Arg_Narrow_Intrinsic; - -// Vector Rounding Shift. -def int_arm_neon_vrshifts : Neon_2Arg_Intrinsic; -def int_arm_neon_vrshiftu : Neon_2Arg_Intrinsic; -def int_arm_neon_vrshiftn : Neon_2Arg_Narrow_Intrinsic; - -// Vector Saturating Shift. -def int_arm_neon_vqshifts : Neon_2Arg_Intrinsic; -def int_arm_neon_vqshiftu : Neon_2Arg_Intrinsic; -def int_arm_neon_vqshiftsu : Neon_2Arg_Intrinsic; -def int_arm_neon_vqshiftns : Neon_2Arg_Narrow_Intrinsic; -def int_arm_neon_vqshiftnu : Neon_2Arg_Narrow_Intrinsic; -def int_arm_neon_vqshiftnsu : Neon_2Arg_Narrow_Intrinsic; - -// Vector Saturating Rounding Shift. -def int_arm_neon_vqrshifts : Neon_2Arg_Intrinsic; -def int_arm_neon_vqrshiftu : Neon_2Arg_Intrinsic; -def int_arm_neon_vqrshiftns : Neon_2Arg_Narrow_Intrinsic; -def int_arm_neon_vqrshiftnu : Neon_2Arg_Narrow_Intrinsic; -def int_arm_neon_vqrshiftnsu : Neon_2Arg_Narrow_Intrinsic; - -// Vector Shift and Insert. -def int_arm_neon_vshiftins : Neon_3Arg_Intrinsic; - -// Vector Absolute Value and Saturating Absolute Value. -def int_arm_neon_vabs : Neon_1Arg_Intrinsic; -def int_arm_neon_vqabs : Neon_1Arg_Intrinsic; - -// Vector Saturating Negate. -def int_arm_neon_vqneg : Neon_1Arg_Intrinsic; - -// Vector Count Leading Sign/Zero Bits. -def int_arm_neon_vcls : Neon_1Arg_Intrinsic; -def int_arm_neon_vclz : Neon_1Arg_Intrinsic; - -// Vector Count One Bits. -def int_arm_neon_vcnt : Neon_1Arg_Intrinsic; - -// Vector Reciprocal Estimate. -def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; - -// Vector Reciprocal Square Root Estimate. -def int_arm_neon_vrsqrte : Neon_1Arg_Intrinsic; - -// Vector Conversions Between Floating-point and Fixed-point. -def int_arm_neon_vcvtfp2fxs : Neon_CvtFPToFx_Intrinsic; -def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; -def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic; -def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic; - -// Vector Conversions Between Half-Precision and Single-Precision. -def int_arm_neon_vcvtfp2hf - : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; -def int_arm_neon_vcvthf2fp - : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; - -// Narrowing Saturating Vector Moves. -def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic; -def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic; -def int_arm_neon_vqmovnsu : Neon_1Arg_Narrow_Intrinsic; - -// Vector Table Lookup. -// The first 1-4 arguments are the table. -def int_arm_neon_vtbl1 : Neon_Tbl2Arg_Intrinsic; -def int_arm_neon_vtbl2 : Neon_Tbl3Arg_Intrinsic; -def int_arm_neon_vtbl3 : Neon_Tbl4Arg_Intrinsic; -def int_arm_neon_vtbl4 : Neon_Tbl5Arg_Intrinsic; - -// 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_arm_neon_vtbx1 : Neon_Tbl3Arg_Intrinsic; -def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; -def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; -def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; - -let TargetPrefix = "arm" in { - - // De-interleaving vector loads from N-element structures. - // Source operands are the address and alignment. - def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], - [llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - def int_arm_neon_vld2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - def int_arm_neon_vld3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>], - [llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], - [llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - - // Vector load N-element structure to one lane. - // Source operands are: the address, the N input vectors (since only one - // lane is assigned), the lane number, and the alignment. - def int_arm_neon_vld2lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [llvm_ptr_ty, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_i32_ty, - llvm_i32_ty], [IntrReadArgMem]>; - def int_arm_neon_vld3lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>], - [llvm_ptr_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i32_ty, llvm_i32_ty], - [IntrReadArgMem]>; - def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], - [llvm_ptr_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_i32_ty, - llvm_i32_ty], [IntrReadArgMem]>; - - // Interleaving vector stores from N-element structures. - // Source operands are: the address, the N vectors, and the alignment. - def int_arm_neon_vst1 : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_arm_neon_vst2 : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, llvm_i32_ty], - [IntrReadWriteArgMem]>; - def int_arm_neon_vst3 : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_arm_neon_vst4 : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_i32_ty], - [IntrReadWriteArgMem]>; - - // Vector store N-element structure from one lane. - // Source operands are: the address, the N vectors, the lane number, and - // the alignment. - def int_arm_neon_vst2lane : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, llvm_i32_ty, - llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_arm_neon_vst3lane : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i32_ty, llvm_i32_ty], - [IntrReadWriteArgMem]>; - def int_arm_neon_vst4lane : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_i32_ty, - llvm_i32_ty], [IntrReadWriteArgMem]>; -} diff --git a/include/llvm/IntrinsicsCellSPU.td b/include/llvm/IntrinsicsCellSPU.td deleted file mode 100644 index 1e311bb..0000000 --- a/include/llvm/IntrinsicsCellSPU.td +++ /dev/null @@ -1,242 +0,0 @@ -//==- IntrinsicsCellSPU.td - Cell SDK intrinsics -*- tablegen -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// Department at The Aerospace Corporation and is distributed under the -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Cell SPU Instructions: -//===----------------------------------------------------------------------===// -// TODO Items (not urgent today, but would be nice, low priority) -// -// ANDBI, ORBI: SPU constructs a 4-byte constant for these instructions by -// concatenating the byte argument b as "bbbb". Could recognize this bit pattern -// in 16-bit and 32-bit constants and reduce instruction count. -//===----------------------------------------------------------------------===// - -// 7-bit integer type, used as an immediate: -def cell_i7_ty: LLVMType<i8>; -def cell_i8_ty: LLVMType<i8>; - -// Keep this here until it's actually supported: -def llvm_i128_ty : LLVMType<i128>; - -class v16i8_u7imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, cell_i7_ty], - [IntrNoMem]>; - -class v16i8_u8imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; - -class v16i8_s10imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; - -class v16i8_u16imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; - -class v16i8_rr<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - -class v8i16_s10imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i16_ty], - [IntrNoMem]>; - -class v8i16_u16imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i16_ty], - [IntrNoMem]>; - -class v8i16_rr<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - -class v4i32_rr<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - -class v4i32_u7imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, cell_i7_ty], - [IntrNoMem]>; - -class v4i32_s10imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i16_ty], - [IntrNoMem]>; - -class v4i32_u16imm<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i16_ty], - [IntrNoMem]>; - -class v4f32_rr<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - -class v4f32_rrr<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - -class v2f64_rr<string builtin_suffix> : - GCCBuiltin<!strconcat("__builtin_si_", builtin_suffix)>, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - -// All Cell SPU intrinsics start with "llvm.spu.". -let TargetPrefix = "spu" in { - def int_spu_si_fsmbi : v8i16_u16imm<"fsmbi">; - def int_spu_si_ah : v8i16_rr<"ah">; - def int_spu_si_ahi : v8i16_s10imm<"ahi">; - def int_spu_si_a : v4i32_rr<"a">; - def int_spu_si_ai : v4i32_s10imm<"ai">; - def int_spu_si_sfh : v8i16_rr<"sfh">; - def int_spu_si_sfhi : v8i16_s10imm<"sfhi">; - def int_spu_si_sf : v4i32_rr<"sf">; - def int_spu_si_sfi : v4i32_s10imm<"sfi">; - def int_spu_si_addx : v4i32_rr<"addx">; - def int_spu_si_cg : v4i32_rr<"cg">; - def int_spu_si_cgx : v4i32_rr<"cgx">; - def int_spu_si_sfx : v4i32_rr<"sfx">; - def int_spu_si_bg : v4i32_rr<"bg">; - def int_spu_si_bgx : v4i32_rr<"bgx">; - def int_spu_si_mpy : // This is special: - GCCBuiltin<"__builtin_si_mpy">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_spu_si_mpyu : // This is special: - GCCBuiltin<"__builtin_si_mpyu">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_spu_si_mpyi : // This is special: - GCCBuiltin<"__builtin_si_mpyi">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_spu_si_mpyui : // This is special: - GCCBuiltin<"__builtin_si_mpyui">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_spu_si_mpya : // This is special: - GCCBuiltin<"__builtin_si_mpya">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_spu_si_mpyh : // This is special: - GCCBuiltin<"__builtin_si_mpyh">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_spu_si_mpys : // This is special: - GCCBuiltin<"__builtin_si_mpys">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_spu_si_mpyhh : // This is special: - GCCBuiltin<"__builtin_si_mpyhh">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_spu_si_mpyhha : // This is special: - GCCBuiltin<"__builtin_si_mpyhha">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_spu_si_mpyhhu : // This is special: - GCCBuiltin<"__builtin_si_mpyhhu">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_spu_si_mpyhhau : // This is special: - GCCBuiltin<"__builtin_si_mpyhhau">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - - def int_spu_si_shli: v4i32_u7imm<"shli">; - - def int_spu_si_shlqbi: - GCCBuiltin<!strconcat("__builtin_si_", "shlqbi")>, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem]>; - - def int_spu_si_shlqbii: v16i8_u7imm<"shlqbii">; - def int_spu_si_shlqby: - GCCBuiltin<!strconcat("__builtin_si_", "shlqby")>, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_spu_si_shlqbyi: v16i8_u7imm<"shlqbyi">; - - def int_spu_si_ceq: v4i32_rr<"ceq">; - def int_spu_si_ceqi: v4i32_s10imm<"ceqi">; - def int_spu_si_ceqb: v16i8_rr<"ceqb">; - def int_spu_si_ceqbi: v16i8_u8imm<"ceqbi">; - def int_spu_si_ceqh: v8i16_rr<"ceqh">; - def int_spu_si_ceqhi: v8i16_s10imm<"ceqhi">; - def int_spu_si_cgt: v4i32_rr<"cgt">; - def int_spu_si_cgti: v4i32_s10imm<"cgti">; - def int_spu_si_cgtb: v16i8_rr<"cgtb">; - def int_spu_si_cgtbi: v16i8_u8imm<"cgtbi">; - def int_spu_si_cgth: v8i16_rr<"cgth">; - def int_spu_si_cgthi: v8i16_s10imm<"cgthi">; - def int_spu_si_clgtb: v16i8_rr<"clgtb">; - def int_spu_si_clgtbi: v16i8_u8imm<"clgtbi">; - def int_spu_si_clgth: v8i16_rr<"clgth">; - def int_spu_si_clgthi: v8i16_s10imm<"clgthi">; - def int_spu_si_clgt: v4i32_rr<"clgt">; - def int_spu_si_clgti: v4i32_s10imm<"clgti">; - - def int_spu_si_and: v4i32_rr<"and">; - def int_spu_si_andbi: v16i8_u8imm<"andbi">; - def int_spu_si_andc: v4i32_rr<"andc">; - def int_spu_si_andhi: v8i16_s10imm<"andhi">; - def int_spu_si_andi: v4i32_s10imm<"andi">; - - def int_spu_si_or: v4i32_rr<"or">; - def int_spu_si_orbi: v16i8_u8imm<"orbi">; - def int_spu_si_orc: v4i32_rr<"orc">; - def int_spu_si_orhi: v8i16_s10imm<"orhi">; - def int_spu_si_ori: v4i32_s10imm<"ori">; - - def int_spu_si_xor: v4i32_rr<"xor">; - def int_spu_si_xorbi: v16i8_u8imm<"xorbi">; - def int_spu_si_xorhi: v8i16_s10imm<"xorhi">; - def int_spu_si_xori: v4i32_s10imm<"xori">; - - def int_spu_si_nor: v4i32_rr<"nor">; - def int_spu_si_nand: v4i32_rr<"nand">; - - def int_spu_si_fa: v4f32_rr<"fa">; - def int_spu_si_fs: v4f32_rr<"fs">; - def int_spu_si_fm: v4f32_rr<"fm">; - - def int_spu_si_fceq: v4f32_rr<"fceq">; - def int_spu_si_fcmeq: v4f32_rr<"fcmeq">; - def int_spu_si_fcgt: v4f32_rr<"fcgt">; - def int_spu_si_fcmgt: v4f32_rr<"fcmgt">; - - def int_spu_si_fma: v4f32_rrr<"fma">; - def int_spu_si_fnms: v4f32_rrr<"fnms">; - def int_spu_si_fms: v4f32_rrr<"fms">; - - def int_spu_si_dfa: v2f64_rr<"dfa">; - def int_spu_si_dfs: v2f64_rr<"dfs">; - def int_spu_si_dfm: v2f64_rr<"dfm">; - -//def int_spu_si_dfceq: v2f64_rr<"dfceq">; -//def int_spu_si_dfcmeq: v2f64_rr<"dfcmeq">; -//def int_spu_si_dfcgt: v2f64_rr<"dfcgt">; -//def int_spu_si_dfcmgt: v2f64_rr<"dfcmgt">; - - def int_spu_si_dfnma: v2f64_rr<"dfnma">; - def int_spu_si_dfma: v2f64_rr<"dfma">; - def int_spu_si_dfnms: v2f64_rr<"dfnms">; - def int_spu_si_dfms: v2f64_rr<"dfms">; -} diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index fe4c92a..d29775a 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -19,20 +19,20 @@ #include "llvm/Analysis/DomPrinter.h" #include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/IntervalPartition.h" +#include "llvm/Analysis/Lint.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/RegionPass.h" #include "llvm/Analysis/RegionPrinter.h" #include "llvm/Analysis/ScalarEvolution.h" -#include "llvm/Analysis/Lint.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/Function.h" -#include "llvm/Transforms/Instrumentation.h" +#include "llvm/IR/Function.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Vectorize.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" +#include "llvm/Transforms/Vectorize.h" #include <cstdlib> namespace { @@ -60,10 +60,12 @@ namespace { (void) llvm::createCFGSimplificationPass(); (void) llvm::createConstantMergePass(); (void) llvm::createConstantPropagationPass(); + (void) llvm::createCostModelAnalysisPass(); (void) llvm::createDeadArgEliminationPass(); (void) llvm::createDeadCodeEliminationPass(); (void) llvm::createDeadInstEliminationPass(); (void) llvm::createDeadStoreEliminationPass(); + (void) llvm::createDependenceAnalysisPass(); (void) llvm::createDomOnlyPrinterPass(); (void) llvm::createDomPrinterPass(); (void) llvm::createDomOnlyViewerPass(); @@ -81,11 +83,10 @@ namespace { (void) llvm::createIPSCCPPass(); (void) llvm::createIndVarSimplifyPass(); (void) llvm::createInstructionCombiningPass(); - (void) llvm::createInternalizePass(false); + (void) llvm::createInternalizePass(); (void) llvm::createLCSSAPass(); (void) llvm::createLICMPass(); (void) llvm::createLazyValueInfoPass(); - (void) llvm::createLoopDependenceAnalysisPass(); (void) llvm::createLoopExtractorPass(); (void) llvm::createLoopSimplifyPass(); (void) llvm::createLoopStrengthReducePass(); @@ -141,6 +142,7 @@ namespace { (void) llvm::createLoopDeletionPass(); (void) llvm::createPostDomTree(); (void) llvm::createInstructionNamerPass(); + (void) llvm::createMetaRenamerPass(); (void) llvm::createFunctionAttrsPass(); (void) llvm::createMergeFunctionsPass(); (void) llvm::createPrintModulePass(0); @@ -154,6 +156,7 @@ namespace { (void) llvm::createCorrelatedValuePropagationPass(); (void) llvm::createMemDepPrinter(); (void) llvm::createInstructionSimplifierPass(); + (void) llvm::createLoopVectorizePass(); (void) llvm::createBBVectorizePass(); (void)new llvm::IntervalPartition(); diff --git a/include/llvm/LinkAllVMCore.h b/include/llvm/LinkAllVMCore.h index 83684c0..6039a63 100644 --- a/include/llvm/LinkAllVMCore.h +++ b/include/llvm/LinkAllVMCore.h @@ -16,13 +16,15 @@ #ifndef LLVM_LINKALLVMCORE_H #define LLVM_LINKALLVMCORE_H -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/InlineAsm.h" #include "llvm/Analysis/Verifier.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Memory.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/Path.h" @@ -30,8 +32,6 @@ #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TimeValue.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/MathExtras.h" #include <cstdlib> namespace { diff --git a/include/llvm/MC/EDInstInfo.h b/include/llvm/MC/EDInstInfo.h deleted file mode 100644 index 5b02467..0000000 --- a/include/llvm/MC/EDInstInfo.h +++ /dev/null @@ -1,29 +0,0 @@ -//===-- llvm/MC/EDInstInfo.h - EDis instruction info ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -#ifndef EDINSTINFO_H -#define EDINSTINFO_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { - -#define EDIS_MAX_OPERANDS 13 -#define EDIS_MAX_SYNTAXES 2 - -struct EDInstInfo { - uint8_t instructionType; - uint8_t numOperands; - uint8_t operandTypes[EDIS_MAX_OPERANDS]; - uint8_t operandFlags[EDIS_MAX_OPERANDS]; - const signed char operandOrders[EDIS_MAX_SYNTAXES][EDIS_MAX_OPERANDS]; -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 1c45090..9a6b703 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -22,7 +22,7 @@ class MCELFObjectTargetWriter; struct MCFixupKindInfo; class MCFragment; class MCInst; -class MCInstFragment; +class MCRelaxableFragment; class MCObjectWriter; class MCSection; class MCValue; @@ -36,10 +36,14 @@ protected: // Can only create subclasses. MCAsmBackend(); unsigned HasReliableSymbolDifference : 1; + unsigned HasDataInCodeSupport : 1; public: virtual ~MCAsmBackend(); + /// lifetime management + virtual void reset() { } + /// createObjectWriter - Create a new MCObjectWriter instance for use by the /// assembler backend to emit the final object file. virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0; @@ -65,6 +69,12 @@ public: return HasReliableSymbolDifference; } + /// hasDataInCodeSupport - Check whether this target implements data-in-code + /// markers. If not, data region directives will be ignored. + bool hasDataInCodeSupport() const { + return HasDataInCodeSupport; + } + /// doesSectionRequireSymbols - Check whether the given section requires that /// all symbols (even temporaries) have symbol table entries. virtual bool doesSectionRequireSymbols(const MCSection &Section) const { @@ -99,7 +109,7 @@ public: /// @} - /// applyFixup - Apply the \arg Value for given \arg Fixup into the provided + /// applyFixup - Apply the \p Value for given \p Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, @@ -120,15 +130,15 @@ public: /// fixup requires the associated instruction to be relaxed. virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, - const MCInstFragment *DF, + const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; /// RelaxInstruction - Relax the instruction in the given fragment to the next /// wider instruction. /// - /// \param Inst - The instruction to relax, which may be the same as the + /// \param Inst The instruction to relax, which may be the same as the /// output. - /// \parm Res [output] - On return, the relaxed instruction. + /// \param [out] Res On return, the relaxed instruction. virtual void relaxInstruction(const MCInst &Inst, MCInst &Res) const = 0; /// @} diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 97aad71..38cf060 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -16,8 +16,8 @@ #ifndef LLVM_TARGET_ASM_INFO_H #define LLVM_TARGET_ASM_INFO_H -#include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MachineLocation.h" #include <cassert> #include <vector> @@ -102,6 +102,9 @@ namespace llvm { /// LabelSuffix - This is appended to emitted labels. const char *LabelSuffix; // Defaults to ":" + /// LabelSuffix - This is appended to emitted labels. + const char *DebugLabelSuffix; // Defaults to ":" + /// GlobalPrefix - If this is set to a non-empty string, it is prepended /// onto all global symbols. This is often used for "_" or ".". const char *GlobalPrefix; // Defaults to "" @@ -426,6 +429,11 @@ namespace llvm { const char *getLabelSuffix() const { return LabelSuffix; } + + const char *getDebugLabelSuffix() const { + return DebugLabelSuffix; + } + const char *getGlobalPrefix() const { return GlobalPrefix; } diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index cf79216..8cb4601 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -21,10 +21,10 @@ class MCSymbolData; /// Encapsulates the layout of an assembly file at a particular point in time. /// -/// Assembly may requiring compute multiple layouts for a particular assembly +/// Assembly may require computing multiple layouts for a particular assembly /// file as part of the relaxation process. This class encapsulates the layout /// at a single point in time in such a way that it is always possible to -/// efficiently compute the exact addresses of any symbol in the assembly file, +/// efficiently compute the exact address of any symbol in the assembly file, /// even during the relaxation process. class MCAsmLayout { public: @@ -39,14 +39,20 @@ private: /// The last fragment which was laid out, or 0 if nothing has been laid /// out. Fragments are always laid out in order, so all fragments with a - /// lower ordinal will be up to date. - mutable DenseMap<const MCSectionData*, MCFragment *> LastValidFragment; + /// lower ordinal will be valid. + mutable DenseMap<const MCSectionData*, MCFragment*> LastValidFragment; /// \brief Make sure that the layout for the given fragment is valid, lazily /// computing it if necessary. - void EnsureValid(const MCFragment *F) const; + void ensureValid(const MCFragment *F) const; - bool isFragmentUpToDate(const MCFragment *F) const; + /// \brief Is the layout for this fragment valid? + bool isFragmentValid(const MCFragment *F) const; + + /// \brief Compute the amount of padding required before this fragment to + /// obey bundling restrictions. + uint64_t computeBundlePadding(const MCFragment *F, + uint64_t FOffset, uint64_t FSize); public: MCAsmLayout(MCAssembler &_Assembler); @@ -54,14 +60,14 @@ public: /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } - /// \brief Invalidate all following fragments because a fragment has been - /// resized. The fragments size should have already been updated. - void Invalidate(MCFragment *F); + /// \brief Invalidate the fragments after F because it has been resized. + /// The fragment's size should have already been updated. + void invalidateFragmentsAfter(MCFragment *F); /// \brief Perform layout for a single fragment, assuming that the previous /// fragment has already been laid out correctly, and the parent section has /// been initialized. - void LayoutFragment(MCFragment *Fragment); + void layoutFragment(MCFragment *Fragment); /// @name Section Access (in layout order) /// @{ diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 1858349..40766b4 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,13 +10,13 @@ #ifndef LLVM_MC_MCASSEMBLER_H #define LLVM_MC_MCASSEMBLER_H -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCInst.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" #include <vector> // FIXME: Shouldn't be needed. @@ -53,7 +53,7 @@ public: FT_Align, FT_Data, FT_Fill, - FT_Inst, + FT_Relaxable, FT_Org, FT_Dwarf, FT_DwarfFrame, @@ -107,44 +107,107 @@ public: unsigned getLayoutOrder() const { return LayoutOrder; } void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } - static bool classof(const MCFragment *O) { return true; } + /// \brief Does this fragment have instructions emitted into it? By default + /// this is false, but specific fragment types may set it to true. + virtual bool hasInstructions() const { return false; } + + /// \brief Should this fragment be placed at the end of an aligned bundle? + virtual bool alignToBundleEnd() const { return false; } + + /// \brief Get the padding size that must be inserted before this fragment. + /// Used for bundling. By default, no padding is inserted. + /// Note that padding size is restricted to 8 bits. This is an optimization + /// to reduce the amount of space used for each fragment. In practice, larger + /// padding should never be required. + virtual uint8_t getBundlePadding() const { + return 0; + } + + /// \brief Set the padding size for this fragment. By default it's a no-op, + /// and only some fragments have a meaningful implementation. + virtual void setBundlePadding(uint8_t N) { + } void dump(); }; -class MCDataFragment : public MCFragment { +class MCEncodedFragment : public MCFragment { virtual void anchor(); - SmallString<32> Contents; - - /// Fixups - The list of fixups in this fragment. - std::vector<MCFixup> Fixups; + uint8_t BundlePadding; public: - typedef std::vector<MCFixup>::const_iterator const_fixup_iterator; - typedef std::vector<MCFixup>::iterator fixup_iterator; + MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0) + : MCFragment(FType, SD), BundlePadding(0) + { + } + virtual ~MCEncodedFragment(); -public: - MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} + typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; + typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; - /// @name Accessors - /// @{ + virtual SmallVectorImpl<char> &getContents() = 0; + virtual const SmallVectorImpl<char> &getContents() const = 0; - SmallString<32> &getContents() { return Contents; } - const SmallString<32> &getContents() const { return Contents; } + virtual SmallVectorImpl<MCFixup> &getFixups() = 0; + virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; - /// @} - /// @name Fixup Access - /// @{ + virtual fixup_iterator fixup_begin() = 0; + virtual const_fixup_iterator fixup_begin() const = 0; + virtual fixup_iterator fixup_end() = 0; + virtual const_fixup_iterator fixup_end() const = 0; + + virtual uint8_t getBundlePadding() const { + return BundlePadding; + } - void addFixup(MCFixup Fixup) { - // Enforce invariant that fixups are in offset order. - assert((Fixups.empty() || Fixup.getOffset() >= Fixups.back().getOffset()) && - "Fixups must be added in order!"); - Fixups.push_back(Fixup); + virtual void setBundlePadding(uint8_t N) { + BundlePadding = N; } - std::vector<MCFixup> &getFixups() { return Fixups; } - const std::vector<MCFixup> &getFixups() const { return Fixups; } + static bool classof(const MCFragment *F) { + MCFragment::FragmentType Kind = F->getKind(); + return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data; + } +}; + +/// Fragment for data and encoded instructions. +/// +class MCDataFragment : public MCEncodedFragment { + virtual void anchor(); + + /// \brief Does this fragment contain encoded instructions anywhere in it? + bool HasInstructions; + + /// \brief Should this fragment be aligned to the end of a bundle? + bool AlignToBundleEnd; + + SmallVector<char, 32> Contents; + + /// Fixups - The list of fixups in this fragment. + SmallVector<MCFixup, 4> Fixups; +public: + MCDataFragment(MCSectionData *SD = 0) + : MCEncodedFragment(FT_Data, SD), + HasInstructions(false), AlignToBundleEnd(false) + { + } + + virtual SmallVectorImpl<char> &getContents() { return Contents; } + virtual const SmallVectorImpl<char> &getContents() const { return Contents; } + + SmallVectorImpl<MCFixup> &getFixups() { + return Fixups; + } + + const SmallVectorImpl<MCFixup> &getFixups() const { + return Fixups; + } + + virtual bool hasInstructions() const { return HasInstructions; } + virtual void setHasInstructions(bool V) { HasInstructions = V; } + + virtual bool alignToBundleEnd() const { return AlignToBundleEnd; } + virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } fixup_iterator fixup_begin() { return Fixups.begin(); } const_fixup_iterator fixup_begin() const { return Fixups.begin(); } @@ -152,61 +215,46 @@ public: fixup_iterator fixup_end() {return Fixups.end();} const_fixup_iterator fixup_end() const {return Fixups.end();} - size_t fixup_size() const { return Fixups.size(); } - - /// @} - static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; } - static bool classof(const MCDataFragment *) { return true; } }; -// FIXME: This current incarnation of MCInstFragment doesn't make much sense, as -// it is almost entirely a duplicate of MCDataFragment. If we decide to stick -// with this approach (as opposed to making MCInstFragment a very light weight -// object with just the MCInst and a code size, then we should just change -// MCDataFragment to have an optional MCInst at its end. -class MCInstFragment : public MCFragment { +/// A relaxable fragment holds on to its MCInst, since it may need to be +/// relaxed during the assembler layout and relaxation stage. +/// +class MCRelaxableFragment : public MCEncodedFragment { virtual void anchor(); /// Inst - The instruction this is a fragment for. MCInst Inst; - /// Code - Binary data for the currently encoded instruction. - SmallString<8> Code; + /// Contents - Binary data for the currently encoded instruction. + SmallVector<char, 8> Contents; /// Fixups - The list of fixups in this fragment. SmallVector<MCFixup, 1> Fixups; public: - typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; - typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; - -public: - MCInstFragment(const MCInst &_Inst, MCSectionData *SD = 0) - : MCFragment(FT_Inst, SD), Inst(_Inst) { + MCRelaxableFragment(const MCInst &_Inst, MCSectionData *SD = 0) + : MCEncodedFragment(FT_Relaxable, SD), Inst(_Inst) { } - /// @name Accessors - /// @{ - - SmallVectorImpl<char> &getCode() { return Code; } - const SmallVectorImpl<char> &getCode() const { return Code; } - - unsigned getInstSize() const { return Code.size(); } + virtual SmallVectorImpl<char> &getContents() { return Contents; } + virtual const SmallVectorImpl<char> &getContents() const { return Contents; } - MCInst &getInst() { return Inst; } const MCInst &getInst() const { return Inst; } - void setInst(const MCInst& Value) { Inst = Value; } - /// @} - /// @name Fixup Access - /// @{ + SmallVectorImpl<MCFixup> &getFixups() { + return Fixups; + } - SmallVectorImpl<MCFixup> &getFixups() { return Fixups; } - const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; } + const SmallVectorImpl<MCFixup> &getFixups() const { + return Fixups; + } + + virtual bool hasInstructions() const { return true; } fixup_iterator fixup_begin() { return Fixups.begin(); } const_fixup_iterator fixup_begin() const { return Fixups.begin(); } @@ -214,14 +262,9 @@ public: fixup_iterator fixup_end() {return Fixups.end();} const_fixup_iterator fixup_end() const {return Fixups.end();} - size_t fixup_size() const { return Fixups.size(); } - - /// @} - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Inst; + return F->getKind() == MCFragment::FT_Relaxable; } - static bool classof(const MCInstFragment *) { return true; } }; class MCAlignFragment : public MCFragment { @@ -233,7 +276,7 @@ class MCAlignFragment : public MCFragment { /// Value - Value to use for filling padding bytes. int64_t Value; - /// ValueSize - The size of the integer (in bytes) of \arg Value. + /// ValueSize - The size of the integer (in bytes) of \p Value. unsigned ValueSize; /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment @@ -271,7 +314,6 @@ public: static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Align; } - static bool classof(const MCAlignFragment *) { return true; } }; class MCFillFragment : public MCFragment { @@ -280,7 +322,7 @@ class MCFillFragment : public MCFragment { /// Value - Value to use for filling bytes. int64_t Value; - /// ValueSize - The size (in bytes) of \arg Value to use when filling, or 0 if + /// ValueSize - The size (in bytes) of \p Value to use when filling, or 0 if /// this is a virtual fill fragment. unsigned ValueSize; @@ -310,7 +352,6 @@ public: static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Fill; } - static bool classof(const MCFillFragment *) { return true; } }; class MCOrgFragment : public MCFragment { @@ -339,7 +380,6 @@ public: static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Org; } - static bool classof(const MCOrgFragment *) { return true; } }; class MCLEBFragment : public MCFragment { @@ -372,7 +412,6 @@ public: static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_LEB; } - static bool classof(const MCLEBFragment *) { return true; } }; class MCDwarfLineAddrFragment : public MCFragment { @@ -409,7 +448,6 @@ public: static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Dwarf; } - static bool classof(const MCDwarfLineAddrFragment *) { return true; } }; class MCDwarfCallFrameFragment : public MCFragment { @@ -439,7 +477,6 @@ public: static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_DwarfFrame; } - static bool classof(const MCDwarfCallFrameFragment *) { return true; } }; // FIXME: Should this be a separate class, or just merged into MCSection? Since @@ -448,8 +485,8 @@ public: class MCSectionData : public ilist_node<MCSectionData> { friend class MCAsmLayout; - MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT - void operator=(const MCSectionData&); // DO NOT IMPLEMENT + MCSectionData(const MCSectionData&) LLVM_DELETED_FUNCTION; + void operator=(const MCSectionData&) LLVM_DELETED_FUNCTION; public: typedef iplist<MCFragment> FragmentListType; @@ -460,6 +497,12 @@ public: typedef FragmentListType::const_reverse_iterator const_reverse_iterator; typedef FragmentListType::reverse_iterator reverse_iterator; + /// \brief Express the state of bundle locked groups while emitting code. + enum BundleLockStateType { + NotBundleLocked, + BundleLocked, + BundleLockedAlignToEnd + }; private: FragmentListType Fragments; const MCSection *Section; @@ -473,6 +516,13 @@ private: /// Alignment - The maximum alignment seen in this section. unsigned Alignment; + /// \brief Keeping track of bundle-locked state. + BundleLockStateType BundleLockState; + + /// \brief We've seen a bundle_lock directive but not its first instruction + /// yet. + bool BundleGroupBeforeFirstInst; + /// @name Assembler Backend Data /// @{ // @@ -525,6 +575,26 @@ public: bool empty() const { return Fragments.empty(); } + bool isBundleLocked() const { + return BundleLockState != NotBundleLocked; + } + + BundleLockStateType getBundleLockState() const { + return BundleLockState; + } + + void setBundleLockState(BundleLockStateType NewState) { + BundleLockState = NewState; + } + + bool isBundleGroupBeforeFirstInst() const { + return BundleGroupBeforeFirstInst; + } + + void setBundleGroupBeforeFirstInst(bool IsFirst) { + BundleGroupBeforeFirstInst = IsFirst; + } + void dump(); /// @} @@ -691,8 +761,8 @@ public: typedef std::vector<DataRegionData>::iterator data_region_iterator; private: - MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT - void operator=(const MCAssembler&); // DO NOT IMPLEMENT + MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION; + void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION; MCContext &Context; @@ -730,6 +800,11 @@ private: // refactoring too. SmallPtrSet<const MCSymbol*, 64> ThumbFuncs; + /// \brief The bundle alignment size currently set in the assembler. + /// + /// By default it's 0, which means bundling is disabled. + unsigned BundleAlignSize; + unsigned RelaxAll : 1; unsigned NoExecStack : 1; unsigned SubsectionsViaSymbols : 1; @@ -746,7 +821,7 @@ private: /// \param Value [out] On return, the value of the fixup as currently laid /// out. /// \return Whether the fixup value was fully resolved. This is true if the - /// \arg Value result is fixed, otherwise the value may change due to + /// \p Value result is fixed, otherwise the value may change due to /// relocation. bool evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, @@ -754,20 +829,22 @@ private: /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). - bool fixupNeedsRelaxation(const MCFixup &Fixup, const MCInstFragment *DF, + bool fixupNeedsRelaxation(const MCFixup &Fixup, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const; /// Check whether the given fragment needs relaxation. - bool fragmentNeedsRelaxation(const MCInstFragment *IF, + bool fragmentNeedsRelaxation(const MCRelaxableFragment *IF, const MCAsmLayout &Layout) const; - /// layoutOnce - Perform one layout iteration and return true if any offsets + /// \brief Perform one layout iteration and return true if any offsets /// were adjusted. bool layoutOnce(MCAsmLayout &Layout); + /// \brief Perform one layout iteration of the given section and return true + /// if any offsets were adjusted. bool layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); - bool relaxInstruction(MCAsmLayout &Layout, MCInstFragment &IF); + bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF); bool relaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); @@ -783,7 +860,7 @@ private: public: /// Compute the effective fragment size assuming it is laid out at the given - /// \arg SectionAddress and \arg FragmentOffset. + /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const; @@ -812,7 +889,7 @@ public: public: /// Construct a new assembler instance. /// - /// \arg OS - The stream to output to. + /// \param OS The stream to output to. // // FIXME: How are we going to parameterize this? Two obvious options are stay // concrete and require clients to pass in a target like object. The other @@ -823,6 +900,10 @@ public: raw_ostream &OS); ~MCAssembler(); + /// Reuse an assembler instance + /// + void reset(); + MCContext &getContext() const { return Context; } MCAsmBackend &getBackend() const { return Backend; } @@ -834,7 +915,7 @@ public: void setWriter(MCObjectWriter &ObjectWriter); /// Finish - Do final processing and write the object to the output stream. - /// \arg Writer is used for custom object writer (as the MCJIT does), + /// \p Writer is used for custom object writer (as the MCJIT does), /// if not specified it is automatically created from backend. void Finish(); @@ -852,6 +933,20 @@ public: bool getNoExecStack() const { return NoExecStack; } void setNoExecStack(bool Value) { NoExecStack = Value; } + bool isBundlingEnabled() const { + return BundleAlignSize != 0; + } + + unsigned getBundleAlignSize() const { + return BundleAlignSize; + } + + void setBundleAlignSize(unsigned Size) { + assert((Size == 0 || !(Size & (Size - 1))) && + "Expect a power-of-two bundle align size"); + BundleAlignSize = Size; + } + /// @name Section List Access /// @{ diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index 4f7d103..9bfa08e 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -29,8 +29,11 @@ protected: // Can only create subclasses. public: virtual ~MCCodeEmitter(); - /// EncodeInstruction - Encode the given \arg Inst to bytes on the output - /// stream \arg OS. + /// Lifetime management + virtual void reset() { } + + /// EncodeInstruction - Encode the given \p Inst to bytes on the output + /// stream \p OS. virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const = 0; }; diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 23652f0..e92d3b9 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -10,10 +10,10 @@ #ifndef LLVM_MC_MCCONTEXT_H #define LLVM_MC_MCCONTEXT_H -#include "llvm/MC/SectionKind.h" -#include "llvm/MC/MCDwarf.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/SectionKind.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" @@ -94,6 +94,12 @@ namespace llvm { /// .secure_log_reset appearing between them. bool SecureLogUsed; + /// The compilation directory to use for DW_AT_comp_dir. + std::string CompilationDir; + + /// The main file name if passed in explicitly. + std::string MainFileName; + /// The dwarf file and directory tables from the dwarf .file directive. std::vector<MCDwarfFile *> MCDwarfFiles; std::vector<StringRef> MCDwarfDirs; @@ -137,11 +143,15 @@ namespace llvm { void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap; + /// Do automatic reset in destructor + bool AutoReset; + MCSymbol *CreateSymbol(StringRef Name); public: explicit MCContext(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, - const MCObjectFileInfo *MOFI, const SourceMgr *Mgr = 0); + const MCObjectFileInfo *MOFI, const SourceMgr *Mgr = 0, + bool DoAutoReset = true); ~MCContext(); const SourceMgr *getSourceManager() const { return SrcMgr; } @@ -154,6 +164,15 @@ namespace llvm { void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } + /// @name Module Lifetime Management + /// @{ + + /// reset - return object to right after construction state to prepare + /// to process a new module + void reset(); + + /// @} + /// @name Symbol Management /// @{ @@ -183,6 +202,7 @@ namespace llvm { /// LookupSymbol - Get the symbol for \p Name, or null. MCSymbol *LookupSymbol(StringRef Name) const; + MCSymbol *LookupSymbol(const Twine &Name) const; /// getSymbols - Get a reference for the symbol table for clients that /// want to, for example, iterate over all symbols. 'const' because we @@ -234,6 +254,24 @@ namespace llvm { /// @name Dwarf Management /// @{ + /// \brief Get the compilation directory for DW_AT_comp_dir + /// This can be overridden by clients which want to control the reported + /// compilation directory and have it be something other than the current + /// working directory. + const std::string &getCompilationDir() const { return CompilationDir; } + + /// \brief Set the compilation directory for DW_AT_comp_dir + /// Override the default (CWD) compilation directory. + void setCompilationDir(StringRef S) { CompilationDir = S.str(); } + + /// \brief Get the main file name for use in error messages and debug + /// info. This can be set to ensure we've got the correct file name + /// after preprocessing or for -save-temps. + const std::string &getMainFileName() const { return MainFileName; } + + /// \brief Set the main file name and override the default. + void setMainFileName(StringRef S) { MainFileName = S.str(); } + /// GetDwarfFile - creates an entry in the dwarf file and directory tables. unsigned GetDwarfFile(StringRef Directory, StringRef FileName, unsigned FileNumber); diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index 53a9ce0..1b6beb2 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -9,8 +9,8 @@ #ifndef MCDISASSEMBLER_H #define MCDISASSEMBLER_H -#include "llvm/Support/DataTypes.h" #include "llvm-c/Disassembler.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -20,8 +20,6 @@ class MemoryObject; class raw_ostream; class MCContext; -struct EDInstInfo; - /// MCDisassembler - Superclass for all disassemblers. Consumes a memory region /// and provides an array of assembly instructions. class MCDisassembler { @@ -84,14 +82,6 @@ public: raw_ostream &vStream, raw_ostream &cStream) const = 0; - /// getEDInfo - Returns the enhanced instruction information corresponding to - /// the disassembler. - /// - /// @return - An array of instruction information, with one entry for - /// each MCInst opcode this disassembler returns. - /// NULL if there is no info for this target. - virtual const EDInstInfo *getEDInfo() const { return (EDInstInfo*)0; } - private: // // Hooks for symbolic disassembly via the public 'C' interface. diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 9e09ddf..3160b61 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -16,10 +16,9 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/StringRef.h" -#include "llvm/MC/MachineLocation.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Dwarf.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/raw_ostream.h" #include <vector> namespace llvm { @@ -59,7 +58,7 @@ namespace llvm { unsigned getDirIndex() const { return DirIndex; } - /// print - Print the value to the stream \arg OS. + /// print - Print the value to the stream \p OS. void print(raw_ostream &OS) const; /// dump - Print the value to stderr. @@ -178,8 +177,8 @@ namespace llvm { class MCLineSection { private: - MCLineSection(const MCLineSection&); // DO NOT IMPLEMENT - void operator=(const MCLineSection&); // DO NOT IMPLEMENT + MCLineSection(const MCLineSection&) LLVM_DELETED_FUNCTION; + void operator=(const MCLineSection&) LLVM_DELETED_FUNCTION; public: // Constructor to create an MCLineSection with an empty MCLineEntries @@ -266,42 +265,115 @@ namespace llvm { class MCCFIInstruction { public: - enum OpType { SameValue, RememberState, RestoreState, Move, RelMove, Escape, - Restore}; + enum OpType { OpSameValue, OpRememberState, OpRestoreState, OpOffset, + OpDefCfaRegister, OpDefCfaOffset, OpDefCfa, OpRelOffset, + OpAdjustCfaOffset, OpEscape, OpRestore, OpUndefined, + OpRegister }; private: OpType Operation; MCSymbol *Label; - // Move to & from location. - MachineLocation Destination; - MachineLocation Source; + 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: - MCCFIInstruction(OpType Op, MCSymbol *L) - : Operation(Op), Label(L) { - assert(Op == RememberState || Op == RestoreState); + static MCCFIInstruction + createOffset(MCSymbol *L, unsigned Register, int Offset) { + return MCCFIInstruction(OpOffset, L, Register, Offset, ""); } - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned Register) - : Operation(Op), Label(L), Destination(Register) { - assert(Op == SameValue || Op == Restore); + + static MCCFIInstruction + createDefCfaRegister(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); } - MCCFIInstruction(MCSymbol *L, const MachineLocation &D, - const MachineLocation &S) - : Operation(Move), Label(L), Destination(D), Source(S) { + + static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { + return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); } - MCCFIInstruction(OpType Op, MCSymbol *L, const MachineLocation &D, - const MachineLocation &S) - : Operation(Op), Label(L), Destination(D), Source(S) { - assert(Op == RelMove); + + static MCCFIInstruction + createDefCfa(MCSymbol *L, unsigned Register, int Offset) { + return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); } - MCCFIInstruction(OpType Op, MCSymbol *L, StringRef Vals) - : Operation(Op), Label(L), Values(Vals.begin(), Vals.end()) { - assert(Op == Escape); + + 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; } - const MachineLocation &getDestination() const { return Destination; } - const MachineLocation &getSource() const { return Source; } + + 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()); } }; diff --git a/include/llvm/MC/MCELF.h b/include/llvm/MC/MCELF.h new file mode 100644 index 0000000..e08f1e6 --- /dev/null +++ b/include/llvm/MC/MCELF.h @@ -0,0 +1,35 @@ +//===- lib/MC/MCELF.h - ELF MC --------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some support functions used by the ELF Streamer and +// ObjectWriter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELF_H +#define LLVM_MC_MCELF_H + +#include "llvm/MC/MCExpr.h" + +namespace llvm { +class MCSymbolData; + +class MCELF { + public: + static void SetBinding(MCSymbolData &SD, unsigned Binding); + static unsigned GetBinding(const MCSymbolData &SD); + static void SetType(MCSymbolData &SD, unsigned Type); + static unsigned GetType(const MCSymbolData &SD); + static void SetVisibility(MCSymbolData &SD, unsigned Visibility); + static unsigned GetVisibility(MCSymbolData &SD); +}; + +} + +#endif diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index abbe188..38cdc72 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -85,6 +85,9 @@ public: const MCFragment &F, const MCFixup &Fixup, bool IsPCRel) const; + virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const; virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); @@ -93,9 +96,9 @@ public: /// @name Accessors /// @{ - uint8_t getOSABI() { return OSABI; } - uint16_t getEMachine() { return EMachine; } - bool hasRelocationAddend() { return HasRelocationAddend; } + uint8_t getOSABI() const { return OSABI; } + uint16_t getEMachine() const { return EMachine; } + bool hasRelocationAddend() const { return HasRelocationAddend; } bool is64Bit() const { return Is64Bit; } bool isN64() const { return IsN64; } /// @} diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h new file mode 100644 index 0000000..ab20ee8 --- /dev/null +++ b/include/llvm/MC/MCELFStreamer.h @@ -0,0 +1,113 @@ +//===- MCELFStreamer.h - MCStreamer ELF Object File Interface ---*- 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_MCELFSTREAMER_H +#define LLVM_MC_MCELFSTREAMER_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/DataTypes.h" +#include <vector> + +namespace llvm { +class MCAsmBackend; +class MCAssembler; +class MCCodeEmitter; +class MCExpr; +class MCInst; +class MCSymbol; +class MCSymbolData; +class raw_ostream; + +class MCELFStreamer : public MCObjectStreamer { +public: + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter) {} + + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter, + MCAssembler *Assembler) + : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler) {} + + virtual ~MCELFStreamer(); + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections(); + virtual void ChangeSection(const MCSection *Section); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitDebugLabel(MCSymbol *Symbol); + 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 void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); + virtual void EmitCOFFSymbolStorageClass(int StorageClass); + virtual void EmitCOFFSymbolType(int Type); + virtual void EndCOFFSymbolDef(); + + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); + + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + uint64_t Size = 0, unsigned ByteAlignment = 0); + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + unsigned AddrSpace); + + virtual void EmitFileDirective(StringRef Filename); + + virtual void EmitTCEntry(const MCSymbol &S); + + virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned); + + virtual void FinishImpl(); + /// @} + +private: + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitInstToData(const MCInst &Inst); + + virtual void EmitBundleAlignMode(unsigned AlignPow2); + virtual void EmitBundleLock(bool AlignToEnd); + virtual void EmitBundleUnlock(); + + void fixSymbolsInTLSFixups(const MCExpr *expr); + + struct LocalCommon { + MCSymbolData *SD; + uint64_t Size; + unsigned ByteAlignment; + }; + + std::vector<LocalCommon> LocalCommons; + + SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet; + + + void SetSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind); + void SetSectionData(); + void SetSectionText(); + void SetSectionBss(); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index f36db3c..475981f 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -99,8 +99,6 @@ public: const MCSection *FindAssociatedSection() const; /// @} - - static bool classof(const MCExpr *) { return true; } }; inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { @@ -132,7 +130,6 @@ public: static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Constant; } - static bool classof(const MCConstantExpr *) { return true; } }; /// MCSymbolRefExpr - Represent a reference to a symbol from inside an @@ -163,6 +160,7 @@ public: VK_TLVP, // Mach-O thread local variable relocation VK_SECREL, // FIXME: We'd really like to use the generic Kinds listed above for these. + VK_ARM_NONE, VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF VK_ARM_GOT, @@ -170,15 +168,30 @@ public: VK_ARM_TPOFF, VK_ARM_GOTTPOFF, VK_ARM_TARGET1, + VK_ARM_TARGET2, + VK_ARM_PREL31, VK_PPC_TOC, // TOC base VK_PPC_TOC_ENTRY, // TOC entry VK_PPC_DARWIN_HA16, // ha16(symbol) VK_PPC_DARWIN_LO16, // lo16(symbol) VK_PPC_GAS_HA16, // symbol@ha - VK_PPC_GAS_LO16, // symbol@l + VK_PPC_GAS_LO16, // symbol@l VK_PPC_TPREL16_HA, // symbol@tprel@ha VK_PPC_TPREL16_LO, // symbol@tprel@l + VK_PPC_DTPREL16_HA, // symbol@dtprel@ha + VK_PPC_DTPREL16_LO, // symbol@dtprel@l + VK_PPC_TOC16_HA, // symbol@toc@ha + VK_PPC_TOC16_LO, // symbol@toc@l + VK_PPC_GOT_TPREL16_HA, // symbol@got@tprel@ha + VK_PPC_GOT_TPREL16_LO, // symbol@got@tprel@l + VK_PPC_TLS, // symbol@tls + VK_PPC_GOT_TLSGD16_HA, // symbol@got@tlsgd@ha + VK_PPC_GOT_TLSGD16_LO, // symbol@got@tlsgd@l + VK_PPC_TLSGD, // symbol@tlsgd + VK_PPC_GOT_TLSLD16_HA, // symbol@got@tlsld@ha + VK_PPC_GOT_TLSLD16_LO, // symbol@got@tlsld@l + VK_PPC_TLSLD, // symbol@tlsld VK_Mips_GPREL, VK_Mips_GOT_CALL, @@ -199,7 +212,11 @@ public: VK_Mips_GOT_PAGE, VK_Mips_GOT_OFST, VK_Mips_HIGHER, - VK_Mips_HIGHEST + VK_Mips_HIGHEST, + VK_Mips_GOT_HI16, + VK_Mips_GOT_LO16, + VK_Mips_CALL_HI16, + VK_Mips_CALL_LO16 }; private: @@ -248,7 +265,6 @@ public: static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::SymbolRef; } - static bool classof(const MCSymbolRefExpr *) { return true; } }; /// MCUnaryExpr - Unary assembler expressions. @@ -302,7 +318,6 @@ public: static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Unary; } - static bool classof(const MCUnaryExpr *) { return true; } }; /// MCBinaryExpr - Binary assembler expressions. @@ -437,7 +452,6 @@ public: static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Binary; } - static bool classof(const MCBinaryExpr *) { return true; } }; /// MCTargetExpr - This is an extension point for target-specific MCExpr @@ -446,7 +460,7 @@ public: /// NOTE: All subclasses are required to have trivial destructors because /// MCExprs are bump pointer allocated and not destructed. class MCTargetExpr : public MCExpr { - virtual void Anchor(); + virtual void anchor(); protected: MCTargetExpr() : MCExpr(Target) {} virtual ~MCTargetExpr() {} @@ -461,7 +475,6 @@ public: static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; } - static bool classof(const MCTargetExpr *) { return true; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 397a37d..e91c6a2 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -182,7 +182,7 @@ public: void dump() const; /// \brief Dump the MCInst as prettily as possible using the additional MC - /// structures, if given. Operators are separated by the \arg Separator + /// structures, if given. Operators are separated by the \p Separator /// string. void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = 0, const MCInstPrinter *Printer = 0, diff --git a/include/llvm/MC/MCInstBuilder.h b/include/llvm/MC/MCInstBuilder.h new file mode 100644 index 0000000..c5acb26 --- /dev/null +++ b/include/llvm/MC/MCInstBuilder.h @@ -0,0 +1,68 @@ +//===-- llvm/MC/MCInstBuilder.h - Simplify creation of MCInsts --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the MCInstBuilder class for convenient creation of +// MCInsts. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTBUILDER_H +#define LLVM_MC_MCINSTBUILDER_H + +#include "llvm/MC/MCInst.h" + +namespace llvm { + +class MCInstBuilder { + MCInst Inst; + +public: + /// \brief Create a new MCInstBuilder for an MCInst with a specific opcode. + MCInstBuilder(unsigned Opcode) { + Inst.setOpcode(Opcode); + } + + /// \brief Add a new register operand. + MCInstBuilder &addReg(unsigned Reg) { + Inst.addOperand(MCOperand::CreateReg(Reg)); + return *this; + } + + /// \brief Add a new integer immediate operand. + MCInstBuilder &addImm(int64_t Val) { + Inst.addOperand(MCOperand::CreateImm(Val)); + return *this; + } + + /// \brief Add a new floating point immediate operand. + MCInstBuilder &addFPImm(double Val) { + Inst.addOperand(MCOperand::CreateFPImm(Val)); + return *this; + } + + /// \brief Add a new MCExpr operand. + MCInstBuilder &addExpr(const MCExpr *Val) { + Inst.addOperand(MCOperand::CreateExpr(Val)); + return *this; + } + + /// \brief Add a new MCInst operand. + MCInstBuilder &addInst(const MCInst *Val) { + Inst.addOperand(MCOperand::CreateInst(Val)); + return *this; + } + + operator MCInst&() { + return Inst; + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 3c4f28b..a18cbd9 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -10,6 +10,9 @@ #ifndef LLVM_MC_MCINSTPRINTER_H #define LLVM_MC_MCINSTPRINTER_H +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Format.h" + namespace llvm { class MCInst; class raw_ostream; @@ -33,12 +36,19 @@ protected: /// The current set of available features. unsigned AvailableFeatures; + /// True if we are printing marked up assembly. + bool UseMarkup; + + /// True if we are printing immediates as hex. + bool PrintImmHex; + /// Utility function for printing annotations. void printAnnotation(raw_ostream &OS, StringRef Annot); public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) - : CommentStream(0), MAI(mai), MII(mii), MRI(mri), AvailableFeatures(0) {} + : CommentStream(0), MAI(mai), MII(mii), MRI(mri), AvailableFeatures(0), + UseMarkup(0), PrintImmHex(0) {} virtual ~MCInstPrinter(); @@ -59,6 +69,19 @@ public: unsigned getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + + bool getUseMarkup() const { return UseMarkup; } + void setUseMarkup(bool Value) { UseMarkup = Value; } + + /// Utility functions to make adding mark ups simpler. + StringRef markup(StringRef s) const; + StringRef markup(StringRef a, StringRef b) const; + + bool getPrintImmHex() const { return PrintImmHex; } + void setPrintImmHex(bool Value) { PrintImmHex = Value; } + + /// Utility function to print immediates in decimal or hex. + format_object1<int64_t> formatImm(const int64_t Value) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index dbf16d8..9b5415a 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -1,4 +1,4 @@ -//===-- llvm/Mc/McInstrDesc.h - Instruction Descriptors -*- C++ -*-===// +//===-- llvm/MC/MCInstrDesc.h - Instruction Descriptors -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,6 +15,8 @@ #ifndef LLVM_MC_MCINSTRDESC_H #define LLVM_MC_MCINSTRDESC_H +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -144,7 +146,7 @@ public: const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands - /// getOperandConstraint - Returns the value of the specific constraint if + /// \brief Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const { @@ -156,12 +158,12 @@ public: return -1; } - /// getOpcode - Return the opcode number for this descriptor. + /// \brief Return the opcode number for this descriptor. unsigned getOpcode() const { return Opcode; } - /// getNumOperands - Return the number of declared MachineOperands for this + /// \brief Return the number of declared MachineOperands for this /// MachineInstruction. Note that variadic (isVariadic() returns true) /// instructions may have additional operands at the end of the list, and note /// that the machine instruction may include implicit register def/uses as @@ -170,7 +172,7 @@ public: return NumOperands; } - /// getNumDefs - Return the number of MachineOperands that are register + /// \brief Return the number of MachineOperands that are register /// definitions. Register definitions always occur at the start of the /// machine operand list. This is the number of "outs" in the .td file, /// and does not include implicit defs. @@ -178,11 +180,10 @@ public: return NumDefs; } - /// getFlags - Return flags of this instruction. - /// + /// \brief Return flags of this instruction. unsigned getFlags() const { return Flags; } - /// isVariadic - Return true if this instruction can have a variable number of + /// \brief Return true if this instruction can have a variable number of /// operands. In this case, the variable operands will be after the normal /// operands but before the implicit definitions and uses (if any are /// present). @@ -190,35 +191,37 @@ public: return Flags & (1 << MCID::Variadic); } - /// hasOptionalDef - Set if this instruction has an optional definition, e.g. + /// \brief Set if this instruction has an optional definition, e.g. /// ARM instructions which can set condition code if 's' bit is set. bool hasOptionalDef() const { return Flags & (1 << MCID::HasOptionalDef); } - /// isPseudo - Return true if this is a pseudo instruction that doesn't + /// \brief Return true if this is a pseudo instruction that doesn't /// correspond to a real machine instruction. /// bool isPseudo() const { return Flags & (1 << MCID::Pseudo); } + /// \brief Return true if the instruction is a return. bool isReturn() const { return Flags & (1 << MCID::Return); } + /// \brief Return true if the instruction is a call. bool isCall() const { return Flags & (1 << MCID::Call); } - /// isBarrier - Returns true if the specified instruction stops control flow + /// \brief Returns true if the specified instruction stops control flow /// from executing the instruction immediately following it. Examples include /// unconditional branches and return instructions. bool isBarrier() const { return Flags & (1 << MCID::Barrier); } - /// isTerminator - Returns true if this instruction part of the terminator for + /// \brief Returns true if this instruction part of the terminator for /// a basic block. Typically this is things like return and branch /// instructions. /// @@ -228,7 +231,7 @@ public: return Flags & (1 << MCID::Terminator); } - /// isBranch - Returns true if this is a conditional, unconditional, or + /// \brief Returns true if this is a conditional, unconditional, or /// indirect branch. Predicates below can be used to discriminate between /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to /// get more information. @@ -236,13 +239,13 @@ public: return Flags & (1 << MCID::Branch); } - /// isIndirectBranch - Return true if this is an indirect branch, such as a + /// \brief Return true if this is an indirect branch, such as a /// branch through a register. bool isIndirectBranch() const { return Flags & (1 << MCID::IndirectBranch); } - /// isConditionalBranch - Return true if this is a branch which may fall + /// \brief Return true if this is a branch which may fall /// through to the next instruction or may transfer control flow to some other /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more /// information about this branch. @@ -250,7 +253,7 @@ public: return isBranch() & !isBarrier() & !isIndirectBranch(); } - /// isUnconditionalBranch - Return true if this is a branch which always + /// \brief Return true if this is a branch which always /// transfers control flow to some other block. The /// TargetInstrInfo::AnalyzeBranch method can be used to get more information /// about this branch. @@ -258,38 +261,47 @@ public: return isBranch() & isBarrier() & !isIndirectBranch(); } - // 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 - /// values. There are various methods in TargetInstrInfo that can be used to + /// \brief Return true if this is a branch or an instruction which directly + /// writes to the program counter. Considered 'may' affect rather than + /// 'does' affect as things like predication are not taken into account. + bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const { + if (isBranch() || isCall() || isReturn() || isIndirectBranch()) + return true; + unsigned PC = RI.getProgramCounter(); + if (PC == 0) return false; + return hasDefOfPhysReg(MI, PC, RI); + } + + /// \brief 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() const { return Flags & (1 << MCID::Predicable); } - /// isCompare - Return true if this instruction is a comparison. + /// \brief Return true if this instruction is a comparison. bool isCompare() const { return Flags & (1 << MCID::Compare); } - /// isMoveImmediate - Return true if this instruction is a move immediate + /// \brief Return true if this instruction is a move immediate /// (including conditional moves) instruction. bool isMoveImmediate() const { return Flags & (1 << MCID::MoveImm); } - /// isBitcast - Return true if this instruction is a bitcast instruction. - /// + /// \brief Return true if this instruction is a bitcast instruction. bool isBitcast() const { return Flags & (1 << MCID::Bitcast); } - /// isSelect - Return true if this is a select instruction. - /// + /// \brief Return true if this is a select instruction. bool isSelect() const { return Flags & (1 << MCID::Select); } - /// isNotDuplicable - Return true if this instruction cannot be safely + /// \brief Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. bool isNotDuplicable() const { @@ -318,7 +330,7 @@ public: // Side Effect Analysis //===--------------------------------------------------------------------===// - /// mayLoad - Return true if this instruction could possibly read memory. + /// \brief Return true if this instruction could possibly read memory. /// Instructions with this flag set are not necessarily simple load /// instructions, they may load a value and modify it, for example. bool mayLoad() const { @@ -326,7 +338,7 @@ public: } - /// mayStore - Return true if this instruction could possibly modify memory. + /// \brief Return true if this instruction could possibly modify memory. /// Instructions with this flag set are not necessarily simple store /// instructions, they may store a modified value based on their operands, or /// may not actually modify anything, for example. @@ -459,8 +471,7 @@ public: return ImplicitUses; } - /// getNumImplicitUses - Return the number of implicit uses this instruction - /// has. + /// \brief Return the number of implicit uses this instruction has. unsigned getNumImplicitUses() const { if (ImplicitUses == 0) return 0; unsigned i = 0; @@ -482,8 +493,7 @@ public: return ImplicitDefs; } - /// getNumImplicitDefs - Return the number of implicit defs this instruction - /// has. + /// \brief Return the number of implicit defs this instruct has. unsigned getNumImplicitDefs() const { if (ImplicitDefs == 0) return 0; unsigned i = 0; @@ -491,7 +501,7 @@ public: return i; } - /// hasImplicitUseOfPhysReg - Return true if this instruction implicitly + /// \brief Return true if this instruction implicitly /// uses the specified physical register. bool hasImplicitUseOfPhysReg(unsigned Reg) const { if (const uint16_t *ImpUses = ImplicitUses) @@ -500,31 +510,43 @@ public: return false; } - /// hasImplicitDefOfPhysReg - Return true if this instruction implicitly + /// \brief Return true if this instruction implicitly /// defines the specified physical register. - bool hasImplicitDefOfPhysReg(unsigned Reg) const { + bool hasImplicitDefOfPhysReg(unsigned Reg, + const MCRegisterInfo *MRI = 0) const { if (const uint16_t *ImpDefs = ImplicitDefs) for (; *ImpDefs; ++ImpDefs) - if (*ImpDefs == Reg) return true; + if (*ImpDefs == Reg || (MRI && MRI->isSubRegister(Reg, *ImpDefs))) + return true; return false; } - /// getSchedClass - Return the scheduling class for this instruction. The + /// \brief Return true if this instruction defines the specified physical + /// register, either explicitly or implicitly. + bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, + const MCRegisterInfo &RI) const { + for (int i = 0, e = NumDefs; i != e; ++i) + if (MI.getOperand(i).isReg() && + RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg())) + return true; + return hasImplicitDefOfPhysReg(Reg, &RI); + } + + /// \brief Return the scheduling class for this instruction. The /// scheduling class is an index into the InstrItineraryData table. This /// returns zero if there is no known scheduling information for the /// instruction. - /// unsigned getSchedClass() const { return SchedClass; } - /// getSize - Return the number of bytes in the encoding of this instruction, + /// \brief Return the number of bytes in the encoding of this instruction, /// or zero if the encoding size cannot be known from the opcode. unsigned getSize() const { return Size; } - /// findFirstPredOperandIdx() - Find the index of the first operand in the + /// \brief Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if /// none is found. int findFirstPredOperandIdx() const { diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h index c72aabd..f531de8 100644 --- a/include/llvm/MC/MCLabel.h +++ b/include/llvm/MC/MCLabel.h @@ -42,7 +42,7 @@ namespace llvm { /// Label. unsigned incInstance() { return ++Instance; } - /// print - Print the value to the stream \arg OS. + /// print - Print the value to the stream \p OS. void print(raw_ostream &OS) const; /// dump - Print the value to stderr. diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 949d907..3cd278e 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -45,6 +45,13 @@ protected: public: virtual ~MCMachObjectTargetWriter(); + /// @name Lifetime Management + /// @{ + + virtual void reset() {}; + + /// @} + /// @name Accessors /// @{ @@ -111,6 +118,13 @@ public: : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { } + /// @name Lifetime management Methods + /// @{ + + virtual void reset(); + + /// @} + /// @name Utility Methods /// @{ @@ -153,8 +167,8 @@ public: /// WriteSegmentLoadCommand - Write a segment load command. /// - /// \arg NumSections - The number of sections in this segment. - /// \arg SectionDataSize - The total size of the sections. + /// \param NumSections The number of sections in this segment. + /// \param SectionDataSize The total size of the sections. void WriteSegmentLoadCommand(unsigned NumSections, uint64_t VMSize, uint64_t SectionDataStartOffset, @@ -223,8 +237,6 @@ public: /// ComputeSymbolTable - Compute the symbol table data /// /// \param StringTable [out] - The string table data. - /// \param StringIndexMap [out] - Map from symbol names to offsets in the - /// string table. void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, std::vector<MachSymbolData> &LocalSymbolData, std::vector<MachSymbolData> &ExternalSymbolData, @@ -233,6 +245,8 @@ public: void computeSectionAddresses(const MCAssembler &Asm, const MCAsmLayout &Layout); + void markAbsoluteVariableSymbols(MCAssembler &Asm, + const MCAsmLayout &Layout); void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 74e2263..c8444fd 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -84,14 +84,6 @@ protected: /// this is the section to emit them into. const MCSection *CompactUnwindSection; - /// DwarfAccelNamesSection, DwarfAccelObjCSection - /// If we use the DWARF accelerated hash tables then we want toe emit these - /// sections. - const MCSection *DwarfAccelNamesSection; - const MCSection *DwarfAccelObjCSection; - const MCSection *DwarfAccelNamespaceSection; - const MCSection *DwarfAccelTypesSection; - // Dwarf sections for debug info. If a target supports debug info, these must // be set. const MCSection *DwarfAbbrevSection; @@ -106,6 +98,24 @@ protected: const MCSection *DwarfRangesSection; const MCSection *DwarfMacroInfoSection; + // DWARF5 Experimental Debug Info Sections + /// DwarfAccelNamesSection, DwarfAccelObjCSection, + /// DwarfAccelNamespaceSection, DwarfAccelTypesSection - + /// If we use the DWARF accelerated hash tables then we want to emit these + /// sections. + const MCSection *DwarfAccelNamesSection; + const MCSection *DwarfAccelObjCSection; + const MCSection *DwarfAccelNamespaceSection; + const MCSection *DwarfAccelTypesSection; + + /// These are used for the Fission separate debug information files. + const MCSection *DwarfInfoDWOSection; + const MCSection *DwarfAbbrevDWOSection; + const MCSection *DwarfStrDWOSection; + const MCSection *DwarfLineDWOSection; + const MCSection *DwarfLocDWOSection; + const MCSection *DwarfStrOffDWOSection; + // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. const MCSection *TLSExtraDataSection; @@ -194,18 +204,6 @@ public: const MCSection *getCompactUnwindSection() const{ return CompactUnwindSection; } - const MCSection *getDwarfAccelNamesSection() const { - return DwarfAccelNamesSection; - } - const MCSection *getDwarfAccelObjCSection() const { - return DwarfAccelObjCSection; - } - const MCSection *getDwarfAccelNamespaceSection() const { - return DwarfAccelNamespaceSection; - } - const MCSection *getDwarfAccelTypesSection() const { - return DwarfAccelTypesSection; - } const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } const MCSection *getDwarfLineSection() const { return DwarfLineSection; } @@ -221,6 +219,39 @@ public: const MCSection *getDwarfMacroInfoSection() const { return DwarfMacroInfoSection; } + + // DWARF5 Experimental Debug Info Sections + const MCSection *getDwarfAccelNamesSection() const { + return DwarfAccelNamesSection; + } + const MCSection *getDwarfAccelObjCSection() const { + return DwarfAccelObjCSection; + } + const MCSection *getDwarfAccelNamespaceSection() const { + return DwarfAccelNamespaceSection; + } + const MCSection *getDwarfAccelTypesSection() const { + return DwarfAccelTypesSection; + } + const MCSection *getDwarfInfoDWOSection() const { + return DwarfInfoDWOSection; + } + const MCSection *getDwarfAbbrevDWOSection() const { + return DwarfAbbrevDWOSection; + } + const MCSection *getDwarfStrDWOSection() const { + return DwarfStrDWOSection; + } + const MCSection *getDwarfLineDWOSection() const { + return DwarfLineDWOSection; + } + const MCSection *getDwarfLocDWOSection() const { + return DwarfLocDWOSection; + } + const MCSection *getDwarfStrOffDWOSection() const { + return DwarfStrOffDWOSection; + } + const MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; } diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index b59b76c..0ece092 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -45,6 +45,11 @@ protected: MCAssembler *_Assembler); ~MCObjectStreamer(); +public: + /// state management + virtual void reset(); + +protected: MCSectionData *getCurrentSectionData() const { return CurSectionData; } @@ -64,6 +69,8 @@ public: /// @{ virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitDebugLabel(MCSymbol *Symbol); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, unsigned AddrSpace); virtual void EmitULEB128Value(const MCExpr *Value); @@ -71,7 +78,21 @@ public: virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); virtual void ChangeSection(const MCSection *Section); virtual void EmitInstruction(const MCInst &Inst); + + /// \brief Emit an instruction to a special fragment, because this instruction + /// can change its size during relaxation. virtual void EmitInstToFragment(const MCInst &Inst); + + virtual void EmitBundleAlignMode(unsigned AlignPow2); + virtual void EmitBundleLock(bool AlignToEnd); + virtual void EmitBundleUnlock(); + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitValueToAlignment(unsigned ByteAlignment, + int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value); virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, @@ -81,6 +102,8 @@ public: const MCSymbol *Label); virtual void EmitGPRel32Value(const MCExpr *Value); virtual void EmitGPRel64Value(const MCExpr *Value); + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace); virtual void FinishImpl(); /// @} diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 14fe75f..9d5c1a7 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -10,9 +10,9 @@ #ifndef LLVM_MC_MCOBJECTWRITER_H #define LLVM_MC_MCOBJECTWRITER_H -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/raw_ostream.h" #include <cassert> namespace llvm { @@ -51,6 +51,9 @@ protected: // Can only create subclasses. public: virtual ~MCObjectWriter(); + /// lifetime management + virtual void reset() { } + bool isLittleEndian() const { return IsLittleEndian; } raw_ostream &getStream() { return OS; } @@ -173,7 +176,13 @@ public: OS << StringRef(Zeros, N % 16); } + void WriteBytes(SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) { + WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize); + } + void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { + // TODO: this version may need to go away once all fragment contents are + // converted to SmallVector<char, N> assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) && "data size greater than fill size, unexpected large write will occur"); OS << Str; diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index ca163c5..37a69e2 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -34,12 +34,10 @@ public: // Real values. Real, - // Register values (stored in IntVal). Only used by MCTargetAsmLexer. - Register, - // No-value. EndOfStatement, Colon, + Space, Plus, Minus, Tilde, Slash, // '/' BackSlash, // '\' @@ -103,13 +101,6 @@ public: assert(Kind == Integer && "This token isn't an integer!"); return IntVal; } - - /// getRegVal - Get the register number for the current token, which should - /// be a register. - unsigned getRegVal() const { - assert(Kind == Register && "This token isn't a register!"); - return static_cast<unsigned>(IntVal); - } }; /// MCAsmLexer - Generic assembler lexer interface, for use by target specific @@ -126,6 +117,7 @@ class MCAsmLexer { void operator=(const MCAsmLexer &) LLVM_DELETED_FUNCTION; protected: // Can only create subclasses. const char *TokStart; + bool SkipSpace; MCAsmLexer(); @@ -170,11 +162,14 @@ public: /// getKind - Get the kind of current token. AsmToken::TokenKind getKind() const { return CurTok.getKind(); } - /// is - Check if the current token has kind \arg K. + /// is - Check if the current token has kind \p K. bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } - /// isNot - Check if the current token has kind \arg K. + /// isNot - Check if the current token has kind \p K. bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } + + /// setSkipSpace - Set whether spaces should be ignored by the lexer + void setSkipSpace(bool val) { SkipSpace = val; } }; } // End llvm namespace diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index c673a79..b9490fa 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -10,8 +10,8 @@ #ifndef LLVM_MC_MCASMPARSER_H #define LLVM_MC_MCASMPARSER_H -#include "llvm/Support/DataTypes.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class AsmToken; @@ -20,6 +20,9 @@ class MCAsmLexer; class MCAsmParserExtension; class MCContext; class MCExpr; +class MCInstPrinter; +class MCInstrInfo; +class MCParsedAsmOperand; class MCStreamer; class MCTargetAsmParser; class SMLoc; @@ -28,6 +31,16 @@ class SourceMgr; class StringRef; class Twine; +/// MCAsmParserSemaCallback - Generic Sema callback for assembly parser. +class MCAsmParserSemaCallback { +public: + virtual ~MCAsmParserSemaCallback(); + virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc, + unsigned &Size) = 0; + virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, + unsigned &Offset) = 0; +}; + /// MCAsmParser - Generic assembler parser interface, for use by target specific /// assembly parsers. class MCAsmParser { @@ -73,15 +86,26 @@ public: /// Run - Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; - /// Warning - Emit a warning at the location \arg L, with the message \arg - /// Msg. + virtual void setParsingInlineAsm(bool V) = 0; + virtual bool isParsingInlineAsm() = 0; + + /// ParseMSInlineAsm - Parse ms-style inline assembly. + virtual bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, + unsigned &NumOutputs, unsigned &NumInputs, + SmallVectorImpl<std::pair<void *, bool> > &OpDecls, + SmallVectorImpl<std::string> &Constraints, + SmallVectorImpl<std::string> &Clobbers, + const MCInstrInfo *MII, + const MCInstPrinter *IP, + MCAsmParserSemaCallback &SI) = 0; + + /// Warning - Emit a warning at the location \p L, with the message \p Msg. /// /// \return The return value is true, if warnings are fatal. virtual bool Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) = 0; - /// Error - Emit an error at the location \arg L, with the message \arg - /// Msg. + /// Error - Emit an error at the location \p L, with the message \p Msg. /// /// \return The return value is always true, as an idiomatic convenience to /// clients. @@ -100,7 +124,7 @@ public: ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()); /// ParseIdentifier - Parse an identifier or string (as a quoted identifier) - /// and set \arg Res to the identifier contents. + /// and set \p Res to the identifier contents. virtual bool ParseIdentifier(StringRef &Res) = 0; /// \brief Parse up to the end of statement and return the contents from the diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index 59593a8..84b33b5 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -10,8 +10,8 @@ #ifndef LLVM_MC_MCASMPARSEREXTENSION_H #define LLVM_MC_MCASMPARSEREXTENSION_H -#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/Support/SMLoc.h" namespace llvm { @@ -43,8 +43,8 @@ protected: public: virtual ~MCAsmParserExtension(); - /// \brief Initialize the extension for parsing using the given \arg - /// Parser. The extension should use the AsmParser interfaces to register its + /// \brief Initialize the extension for parsing using the given \p Parser. + /// The extension should use the AsmParser interfaces to register its /// parsing routines. virtual void Initialize(MCAsmParser &Parser); diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 2556e5f..60e7887 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -19,15 +19,69 @@ class raw_ostream; /// base class is used by target-independent clients and is the interface /// between parsing an asm instruction and recognizing it. class MCParsedAsmOperand { + /// MCOperandNum - The corresponding MCInst operand number. Only valid when + /// parsing MS-style inline assembly. + unsigned MCOperandNum; + + /// Constraint - The constraint on this operand. Only valid when parsing + /// MS-style inline assembly. + std::string Constraint; + public: MCParsedAsmOperand() {} virtual ~MCParsedAsmOperand() {} + void setConstraint(StringRef C) { Constraint = C.str(); } + StringRef getConstraint() { return Constraint; } + + void setMCOperandNum (unsigned OpNum) { MCOperandNum = OpNum; } + unsigned getMCOperandNum() { return MCOperandNum; } + + unsigned getNameLen() { + assert (getStartLoc().isValid() && "Invalid StartLoc!"); + assert (getEndLoc().isValid() && "Invalid EndLoc!"); + return getEndLoc().getPointer() - getStartLoc().getPointer(); + } + + StringRef getName() { + return StringRef(getStartLoc().getPointer(), getNameLen()); + } + + /// isToken - Is this a token operand? + virtual bool isToken() const = 0; + /// isImm - Is this an immediate operand? + virtual bool isImm() const = 0; + /// isReg - Is this a register operand? + virtual bool isReg() const = 0; + virtual unsigned getReg() const = 0; + + /// isMem - Is this a memory operand? + virtual bool isMem() const = 0; + virtual unsigned getMemSize() const { return 0; } + /// getStartLoc - Get the location of the first token of this operand. virtual SMLoc getStartLoc() const = 0; /// getEndLoc - Get the location of the last token of this operand. virtual SMLoc getEndLoc() const = 0; + /// needAsmRewrite - AsmRewrites happen in both the target-independent and + /// target-dependent parsers. The target-independent parser calls this + /// function to determine if the target-dependent parser has already taken + /// care of the rewrites. Only valid when parsing MS-style inline assembly. + virtual bool needAsmRewrite() const { return true; } + + /// isOffsetOf - Do we need to emit code to get the offset of the variable, + /// rather then the value of the variable? Only valid when parsing MS-style + /// inline assembly. + virtual bool isOffsetOf() const { return false; } + + /// getOffsetOfLoc - Get the location of the offset operator. + virtual SMLoc getOffsetOfLoc() const { return SMLoc(); } + + /// needSizeDirective - Do we need to emit a sizing directive for this + /// operand? Only valid when parsing MS-style inline assembly. + virtual bool needSizeDirective() const { return false; } + /// print - Print a debug representation of the operand to the given stream. virtual void print(raw_ostream &OS) const = 0; /// dump - Print to the debug stream. diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 46a9d71..f5b4ddd 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -22,11 +22,15 @@ namespace llvm { +/// An unsigned integer type large enough to represent all physical registers, +/// but not necessarily virtual registers. +typedef uint16_t MCPhysReg; + /// MCRegisterClass - Base class of TargetRegisterClass. class MCRegisterClass { public: - typedef const uint16_t* iterator; - typedef const uint16_t* const_iterator; + typedef const MCPhysReg* iterator; + typedef const MCPhysReg* const_iterator; const char *Name; const iterator RegsBegin; @@ -148,11 +152,12 @@ private: const MCRegisterDesc *Desc; // Pointer to the descriptor array unsigned NumRegs; // Number of entries in the array unsigned RAReg; // Return address register + unsigned PCReg; // Program counter register const MCRegisterClass *Classes; // Pointer to the regclass array unsigned NumClasses; // Number of entries in the array unsigned NumRegUnits; // Number of regunits. const uint16_t (*RegUnitRoots)[2]; // Pointer to regunit root table. - const uint16_t *DiffLists; // Pointer to the difflists array + const MCPhysReg *DiffLists; // Pointer to the difflists array const char *RegStrings; // Pointer to the string table. const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. @@ -177,7 +182,7 @@ public: /// defined below. class DiffListIterator { uint16_t Val; - const uint16_t *List; + const MCPhysReg *List; protected: /// Create an invalid iterator. Call init() to point to something useful. @@ -186,7 +191,7 @@ public: /// init - Point the iterator to InitVal, decoding subsequent values from /// DiffList. The iterator will initially point to InitVal, sub-classes are /// responsible for skipping the seed value if it is not part of the list. - void init(uint16_t InitVal, const uint16_t *DiffList) { + void init(MCPhysReg InitVal, const MCPhysReg *DiffList) { Val = InitVal; List = DiffList; } @@ -196,7 +201,7 @@ public: /// is the caller's responsibility (by checking for a 0 return value). unsigned advance() { assert(isValid() && "Cannot move off the end of the list."); - uint16_t D = *List++; + MCPhysReg D = *List++; Val += D; return D; } @@ -225,13 +230,14 @@ public: friend class MCRegUnitIterator; friend class MCRegUnitRootIterator; - /// InitMCRegisterInfo - Initialize MCRegisterInfo, called by TableGen + /// \brief Initialize MCRegisterInfo, called by TableGen /// auto-generated routines. *DO NOT USE*. void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, + unsigned PC, const MCRegisterClass *C, unsigned NC, const uint16_t (*RURoots)[2], unsigned NRU, - const uint16_t *DL, + const MCPhysReg *DL, const char *Strings, const uint16_t *SubIndices, unsigned NumIndices, @@ -239,6 +245,7 @@ public: Desc = D; NumRegs = NR; RAReg = RA; + PCReg = PC; Classes = C; DiffLists = DL; RegStrings = Strings; @@ -250,7 +257,7 @@ public: RegEncodingTable = RET; } - /// mapLLVMRegsToDwarfRegs - Used to initialize LLVM register to Dwarf + /// \brief Used to initialize LLVM register to Dwarf /// register number mapping. Called by TableGen auto-generated routines. /// *DO NOT USE*. void mapLLVMRegsToDwarfRegs(const DwarfLLVMRegPair *Map, unsigned Size, @@ -264,7 +271,7 @@ public: } } - /// mapDwarfRegsToLLVMRegs - Used to initialize Dwarf register to LLVM + /// \brief Used to initialize Dwarf register to LLVM /// register number mapping. Called by TableGen auto-generated routines. /// *DO NOT USE*. void mapDwarfRegsToLLVMRegs(const DwarfLLVMRegPair *Map, unsigned Size, @@ -287,70 +294,80 @@ public: L2SEHRegs[LLVMReg] = SEHReg; } - /// getRARegister - This method should return the register where the return + /// \brief This method should return the register where the return /// address can be found. unsigned getRARegister() const { return RAReg; } + /// Return the register which is the program counter. + unsigned getProgramCounter() const { + return PCReg; + } + const MCRegisterDesc &operator[](unsigned RegNo) const { assert(RegNo < NumRegs && "Attempting to access record for invalid register number!"); return Desc[RegNo]; } - /// Provide a get method, equivalent to [], but more useful if we have a + /// \brief Provide a get method, equivalent to [], but more useful with a /// pointer to this object. - /// const MCRegisterDesc &get(unsigned RegNo) const { return operator[](RegNo); } - /// getSubReg - Returns the physical register number of sub-register "Index" + /// \brief Returns the physical register number of sub-register "Index" /// for physical register RegNo. Return zero if the sub-register does not /// exist. unsigned getSubReg(unsigned Reg, unsigned Idx) const; - /// getMatchingSuperReg - Return a super-register of the specified register + /// \brief Return a super-register of the specified register /// Reg so its sub-register of index SubIdx is Reg. unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC) const; - /// getSubRegIndex - For a given register pair, return the sub-register index + /// \brief For a given register pair, return the sub-register index /// if the second register is a sub-register of the first. Return zero /// otherwise. unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const; - /// getName - Return the human-readable symbolic target-specific name for the + /// \brief Return the human-readable symbolic target-specific name for the /// specified physical register. const char *getName(unsigned RegNo) const { return RegStrings + get(RegNo).Name; } - /// getNumRegs - Return the number of registers this target has (useful for + /// \brief Return the number of registers this target has (useful for /// sizing arrays holding per register information) unsigned getNumRegs() const { return NumRegs; } - /// getNumRegUnits - Return the number of (native) register units in the + /// \brief Return the number of sub-register indices + /// understood by the target. Index 0 is reserved for the no-op sub-register, + /// while 1 to getNumSubRegIndices() - 1 represent real sub-registers. + unsigned getNumSubRegIndices() const { + return NumSubRegIndices; + } + + /// \brief Return the number of (native) register units in the /// target. Register units are numbered from 0 to getNumRegUnits() - 1. They /// can be accessed through MCRegUnitIterator defined below. unsigned getNumRegUnits() const { return NumRegUnits; } - /// getDwarfRegNum - Map a target register to an equivalent dwarf register + /// \brief Map a target register to an equivalent dwarf register /// number. Returns -1 if there is no equivalent value. The second /// parameter allows targets to use different numberings for EH info and /// debugging info. int getDwarfRegNum(unsigned RegNum, bool isEH) const; - /// getLLVMRegNum - Map a dwarf register back to a target register. - /// + /// \brief Map a dwarf register back to a target register. int getLLVMRegNum(unsigned RegNum, bool isEH) const; - /// getSEHRegNum - Map a target register to an equivalent SEH register + /// \brief Map a target register to an equivalent SEH register /// number. Returns LLVM register number if there is no equivalent value. int getSEHRegNum(unsigned RegNum) const; @@ -361,20 +378,39 @@ public: return (unsigned)(regclass_end()-regclass_begin()); } - /// getRegClass - Returns the register class associated with the enumeration + /// \brief Returns the register class associated with the enumeration /// value. See class MCOperandInfo. - const MCRegisterClass getRegClass(unsigned i) const { + const MCRegisterClass& getRegClass(unsigned i) const { assert(i < getNumRegClasses() && "Register Class ID out of range"); return Classes[i]; } - /// getEncodingValue - Returns the encoding for RegNo + /// \brief Returns the encoding for RegNo uint16_t getEncodingValue(unsigned RegNo) const { assert(RegNo < NumRegs && "Attempting to get encoding for invalid register number!"); return RegEncodingTable[RegNo]; } + /// \brief Returns true if RegB is a sub-register of RegA. + bool isSubRegister(unsigned RegA, unsigned RegB) const { + return isSuperRegister(RegB, RegA); + } + + /// \brief Returns true if RegB is a super-register of RegA. + bool isSuperRegister(unsigned RegA, unsigned RegB) const; + + /// \brief Returns true if RegB is a sub-register of RegA or if RegB == RegA. + bool isSubRegisterEq(unsigned RegA, unsigned RegB) const { + return isSuperRegisterEq(RegB, RegA); + } + + /// \brief Returns true if RegB is a super-register of RegA or if + /// RegB == RegA. + bool isSuperRegisterEq(unsigned RegA, unsigned RegB) const { + return RegA == RegB || isSuperRegister(RegA, RegB); + } + }; //===----------------------------------------------------------------------===// @@ -415,6 +451,15 @@ public: } }; +// Definition for isSuperRegister. Put it down here since it needs the +// iterator defined above in addition to the MCRegisterInfo class itself. +inline bool MCRegisterInfo::isSuperRegister(unsigned RegA, unsigned RegB) const{ + for (MCSuperRegIterator I(RegA, this); I.isValid(); ++I) + if (*I == RegB) + return true; + return false; +} + //===----------------------------------------------------------------------===// // Register Units //===----------------------------------------------------------------------===// @@ -434,6 +479,7 @@ public: /// MCRegUnitIterator - Create an iterator that traverses the register units /// in Reg. MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + assert(Reg && "Null register has no regunits"); // Decode the RegUnits MCRegisterDesc field. unsigned RU = MCRI->get(Reg).RegUnits; unsigned Scale = RU & 15; @@ -473,17 +519,17 @@ public: Reg1 = MCRI->RegUnitRoots[RegUnit][1]; } - /// Dereference to get the current root register. + /// \brief Dereference to get the current root register. unsigned operator*() const { return Reg0; } - /// isValid - Check if the iterator is at the end of the list. + /// \brief Check if the iterator is at the end of the list. bool isValid() const { return Reg0; } - /// Preincrement to move to the next root register. + /// \brief Preincrement to move to the next root register. void operator++() { assert(isValid() && "Cannot move off the end of the list."); Reg0 = Reg1; diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 3b1cdf1..0c71ee5 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -16,17 +16,111 @@ #define LLVM_MC_MCSCHEDMODEL_H #include "llvm/Support/DataTypes.h" +#include <cassert> namespace llvm { struct InstrItinerary; +/// Define a kind of processor resource that will be modeled by the scheduler. +struct MCProcResourceDesc { +#ifndef NDEBUG + const char *Name; +#endif + unsigned NumUnits; // Number of resource of this kind + unsigned SuperIdx; // Index of the resources kind that contains this kind. + + // Buffered resources may be consumed at some indeterminate cycle after + // dispatch (e.g. for instructions that may issue out-of-order). Unbuffered + // resources always consume their resource some fixed number of cycles after + // dispatch (e.g. for instruction interlocking that may stall the pipeline). + bool IsBuffered; + + bool operator==(const MCProcResourceDesc &Other) const { + return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx + && IsBuffered == Other.IsBuffered; + } +}; + +/// Identify one of the processor resource kinds consumed by a particular +/// scheduling class for the specified number of cycles. +struct MCWriteProcResEntry { + unsigned ProcResourceIdx; + unsigned Cycles; + + bool operator==(const MCWriteProcResEntry &Other) const { + return ProcResourceIdx == Other.ProcResourceIdx && Cycles == Other.Cycles; + } +}; + +/// Specify the latency in cpu cycles for a particular scheduling class and def +/// index. -1 indicates an invalid latency. Heuristics would typically consider +/// an instruction with invalid latency to have infinite latency. Also identify +/// the WriteResources of this def. When the operand expands to a sequence of +/// writes, this ID is the last write in the sequence. +struct MCWriteLatencyEntry { + int Cycles; + unsigned WriteResourceID; + + bool operator==(const MCWriteLatencyEntry &Other) const { + return Cycles == Other.Cycles && WriteResourceID == Other.WriteResourceID; + } +}; + +/// Specify the number of cycles allowed after instruction issue before a +/// particular use operand reads its registers. This effectively reduces the +/// write's latency. Here we allow negative cycles for corner cases where +/// latency increases. This rule only applies when the entry's WriteResource +/// matches the write's WriteResource. +/// +/// MCReadAdvanceEntries are sorted first by operand index (UseIdx), then by +/// WriteResourceIdx. +struct MCReadAdvanceEntry { + unsigned UseIdx; + unsigned WriteResourceID; + int Cycles; + + bool operator==(const MCReadAdvanceEntry &Other) const { + return UseIdx == Other.UseIdx && WriteResourceID == Other.WriteResourceID + && Cycles == Other.Cycles; + } +}; + +/// Summarize the scheduling resources required for an instruction of a +/// particular scheduling class. +/// +/// Defined as an aggregate struct for creating tables with initializer lists. +struct MCSchedClassDesc { + static const unsigned short InvalidNumMicroOps = UINT16_MAX; + static const unsigned short VariantNumMicroOps = UINT16_MAX - 1; + +#ifndef NDEBUG + const char* Name; +#endif + unsigned short NumMicroOps; + bool BeginGroup; + bool EndGroup; + unsigned WriteProcResIdx; // First index into WriteProcResTable. + unsigned NumWriteProcResEntries; + unsigned WriteLatencyIdx; // First index into WriteLatencyTable. + unsigned NumWriteLatencyEntries; + unsigned ReadAdvanceIdx; // First index into ReadAdvanceTable. + unsigned NumReadAdvanceEntries; + + bool isValid() const { + return NumMicroOps != InvalidNumMicroOps; + } + bool isVariant() const { + return NumMicroOps == VariantNumMicroOps; + } +}; + /// Machine model for scheduling, bundling, and heuristics. /// /// The machine model directly provides basic information about the /// microarchitecture to the scheduler in the form of properties. It also -/// optionally refers to scheduler resources tables and itinerary -/// tables. Scheduler resources tables model the latency and cost for each +/// 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 /// provides a detailed reservation table describing each cycle of instruction /// execution. Subtargets may define any or all of the above categories of data @@ -84,8 +178,11 @@ public: static const unsigned DefaultMispredictPenalty = 10; private: - // TODO: Add a reference to proc resource types and sched resource tables. - + unsigned ProcID; + const MCProcResourceDesc *ProcResourceTable; + const MCSchedClassDesc *SchedClassTable; + unsigned NumProcResourceKinds; + unsigned NumSchedClasses; // Instruction itinerary tables used by InstrItineraryData. friend class InstrItineraryData; const InstrItinerary *InstrItineraries; @@ -100,13 +197,45 @@ public: LoadLatency(DefaultLoadLatency), HighLatency(DefaultHighLatency), MispredictPenalty(DefaultMispredictPenalty), - InstrItineraries(0) {} + ProcID(0), ProcResourceTable(0), SchedClassTable(0), + NumProcResourceKinds(0), NumSchedClasses(0), + InstrItineraries(0) { + (void)NumProcResourceKinds; + (void)NumSchedClasses; + } // Table-gen driven ctor. MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned mp, + unsigned pi, const MCProcResourceDesc *pr, + const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, const InstrItinerary *ii): IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl), - MispredictPenalty(mp), InstrItineraries(ii){} + MispredictPenalty(mp), 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; } + + unsigned getNumProcResourceKinds() const { + return NumProcResourceKinds; + } + + const MCProcResourceDesc *getProcResource(unsigned ProcResourceIdx) const { + assert(hasInstrSchedModel() && "No scheduling machine model"); + + assert(ProcResourceIdx < NumProcResourceKinds && "bad proc resource idx"); + return &ProcResourceTable[ProcResourceIdx]; + } + + const MCSchedClassDesc *getSchedClassDesc(unsigned SchedClassIdx) const { + assert(hasInstrSchedModel() && "No scheduling machine model"); + + assert(SchedClassIdx < NumSchedClasses && "bad scheduling class idx"); + return &SchedClassTable[SchedClassIdx]; + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index f90ad6a..5d6cac2 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -14,6 +14,7 @@ #ifndef LLVM_MC_MCSECTION_H #define LLVM_MC_MCSECTION_H +#include "llvm/ADT/StringRef.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Compiler.h" @@ -50,6 +51,11 @@ namespace llvm { virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const = 0; + // Convenience routines to get label names for the beginning/end of a + // section. + virtual std::string getLabelBeginName() const = 0; + virtual std::string getLabelEndName() const = 0; + /// isBaseAddressKnownZero - Return true if we know that this section will /// get a base address of zero. In cases where we know that this is true we /// can emit section offsets as direct references to avoid a subtraction @@ -65,8 +71,6 @@ namespace llvm { /// isVirtualSection - Check whether this section is "virtual", that is /// has no actual object file contents. virtual bool isVirtualSection() const = 0; - - static bool classof(const MCSection *) { return true; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 7eacde5..07c4714 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -14,9 +14,9 @@ #ifndef LLVM_MC_MCSECTIONCOFF_H #define LLVM_MC_MCSECTIONCOFF_H +#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCSection.h" #include "llvm/Support/COFF.h" -#include "llvm/ADT/StringRef.h" namespace llvm { @@ -50,6 +50,12 @@ namespace llvm { bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } + virtual std::string getLabelBeginName() const { + return SectionName.str() + "_begin"; + } + virtual std::string getLabelEndName() const { + return SectionName.str() + "_end"; + } unsigned getCharacteristics() const { return Characteristics; } int getSelection () const { return Selection; } @@ -61,7 +67,6 @@ namespace llvm { static bool classof(const MCSection *S) { return S->getVariant() == SV_COFF; } - static bool classof(const MCSectionCOFF *) { return true; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 7321ca8..4b8b849 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -14,9 +14,11 @@ #ifndef LLVM_MC_MCSECTIONELF_H #define LLVM_MC_MCSECTIONELF_H +#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCSection.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { @@ -57,6 +59,11 @@ public: bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } + virtual std::string getLabelBeginName() const { + return SectionName.str() + "_begin"; } + virtual std::string getLabelEndName() const { + return SectionName.str() + "_end"; + } unsigned getType() const { return Type; } unsigned getFlags() const { return Flags; } unsigned getEntrySize() const { return EntrySize; } @@ -76,7 +83,6 @@ public: static bool classof(const MCSection *S) { return S->getVariant() == SV_ELF; } - static bool classof(const MCSectionELF *) { return true; } // Return the entry size for sections with fixed-width data. static unsigned DetermineEntrySize(SectionKind Kind); diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index 15eb4f4..898f571 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -14,8 +14,8 @@ #ifndef LLVM_MC_MCSECTIONMACHO_H #define LLVM_MC_MCSECTIONMACHO_H -#include "llvm/MC/MCSection.h" #include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCSection.h" namespace llvm { @@ -145,6 +145,14 @@ public: return StringRef(SectionName); } + virtual std::string getLabelBeginName() const { + return StringRef(getSegmentName().str() + getSectionName().str() + "_begin"); + } + + virtual std::string getLabelEndName() const { + return StringRef(getSegmentName().str() + getSectionName().str() + "_end"); + } + unsigned getTypeAndAttributes() const { return TypeAndAttributes; } unsigned getStubSize() const { return Reserved2; } @@ -174,7 +182,6 @@ public: static bool classof(const MCSection *S) { return S->getVariant() == SV_MachO; } - static bool classof(const MCSectionMachO *) { return true; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 91593b9..05a33c5 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -14,12 +14,12 @@ #ifndef LLVM_MC_MCSTREAMER_H #define LLVM_MC_MCSTREAMER_H -#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCWin64EH.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class MCAsmBackend; @@ -55,6 +55,7 @@ namespace llvm { std::vector<MCDwarfFrameInfo> FrameInfos; MCDwarfFrameInfo *getCurrentFrameInfo(); + MCSymbol *EmitCFICommon(); void EnsureValidFrame(); std::vector<MCWin64EHUnwindInfo *> W64UnwindInfos; @@ -69,6 +70,8 @@ namespace llvm { SmallVector<std::pair<const MCSection *, const MCSection *>, 4> SectionStack; + bool AutoInitSections; + protected: MCStreamer(MCContext &Ctx); @@ -89,6 +92,10 @@ namespace llvm { public: virtual ~MCStreamer(); + /// State management + /// + virtual void reset(); + MCContext &getContext() const { return Context; } unsigned getNumFrameInfos() { @@ -213,6 +220,17 @@ namespace llvm { SectionStack.back().first = Section; } + /// 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; @@ -226,6 +244,8 @@ namespace llvm { /// used in an assignment. virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitDebugLabel(MCSymbol *Symbol); + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); @@ -342,7 +362,7 @@ namespace llvm { /// @name Generating Data /// @{ - /// EmitBytes - Emit the bytes in \arg Data into the output. + /// EmitBytes - Emit the bytes in \p Data into the output. /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. @@ -417,7 +437,6 @@ namespace llvm { EmitFill(NumBytes, 0, AddrSpace); } - /// EmitValueToAlignment - Emit some number of copies of @p Value until /// the byte alignment @p ByteAlignment is reached. /// @@ -515,6 +534,8 @@ namespace llvm { 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(); @@ -535,6 +556,20 @@ namespace llvm { /// 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. @@ -554,6 +589,11 @@ namespace llvm { 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. @@ -573,11 +613,11 @@ namespace llvm { /// InstPrint. /// /// \param CE - If given, a code emitter to use to show the instruction - /// encoding inline with the assembly. This method takes ownership of \arg CE. + /// 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 \arg TAB. + /// ownership of \p TAB. /// /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. @@ -594,7 +634,7 @@ namespace llvm { /// createMachOStreamer - Create a machine code streamer which will generate /// Mach-O format object files. /// - /// Takes ownership of \arg TAB and \arg CE. + /// Takes ownership of \p TAB and \p CE. MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll = false); @@ -602,7 +642,7 @@ namespace llvm { /// createWinCOFFStreamer - Create a machine code streamer which will /// generate Microsoft COFF format object files. /// - /// Takes ownership of \arg TAB and \arg CE. + /// Takes ownership of \p TAB and \p CE. MCStreamer *createWinCOFFStreamer(MCContext &Ctx, MCAsmBackend &TAB, MCCodeEmitter &CE, raw_ostream &OS, @@ -617,7 +657,7 @@ namespace llvm { /// createPureStreamer - Create a machine code streamer which will generate /// "pure" MC object files, for use with MC-JIT and testing tools. /// - /// Takes ownership of \arg TAB and \arg CE. + /// Takes ownership of \p TAB and \p CE. MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE); diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 6c96f49..346fb2d 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -14,8 +14,8 @@ #ifndef LLVM_MC_MCSUBTARGET_H #define LLVM_MC_MCSUBTARGET_H -#include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/MCInstrItineraries.h" +#include "llvm/MC/SubtargetFeature.h" #include <string> namespace llvm { @@ -30,7 +30,14 @@ class MCSubtargetInfo { std::string TargetTriple; // Target triple const SubtargetFeatureKV *ProcFeatures; // Processor feature list const SubtargetFeatureKV *ProcDesc; // Processor descriptions - const SubtargetInfoKV *ProcSchedModel; // Scheduler machine model + + // Scheduler machine model + const SubtargetInfoKV *ProcSchedModels; + const MCWriteProcResEntry *WriteProcResTable; + const MCWriteLatencyEntry *WriteLatencyTable; + const MCReadAdvanceEntry *ReadAdvanceTable; + const MCSchedModel *CPUSchedModel; + const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles const unsigned *ForwardingPaths; // Forwarding paths @@ -43,6 +50,9 @@ public: const SubtargetFeatureKV *PF, const SubtargetFeatureKV *PD, const SubtargetInfoKV *ProcSched, + const MCWriteProcResEntry *WPR, + const MCWriteLatencyEntry *WL, + const MCReadAdvanceEntry *RA, const InstrStage *IS, const unsigned *OC, const unsigned *FP, unsigned NF, unsigned NP); @@ -58,9 +68,9 @@ public: return FeatureBits; } - /// ReInitMCSubtargetInfo - Change CPU (and optionally supplemented with - /// feature string), recompute and return feature bits. - uint64_t ReInitMCSubtargetInfo(StringRef CPU, StringRef FS); + /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with + /// feature string). Recompute feature bits and scheduling model. + void InitMCProcessorInfo(StringRef CPU, StringRef FS); /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. @@ -74,9 +84,54 @@ public: /// const MCSchedModel *getSchedModelForCPU(StringRef CPU) const; + /// getSchedModel - Get the machine model for this subtarget's CPU. + /// + const MCSchedModel *getSchedModel() const { return CPUSchedModel; } + + /// Return an iterator at the first process resource consumed by the given + /// scheduling class. + const MCWriteProcResEntry *getWriteProcResBegin( + const MCSchedClassDesc *SC) const { + return &WriteProcResTable[SC->WriteProcResIdx]; + } + const MCWriteProcResEntry *getWriteProcResEnd( + const MCSchedClassDesc *SC) const { + return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries; + } + + const MCWriteLatencyEntry *getWriteLatencyEntry(const MCSchedClassDesc *SC, + unsigned DefIdx) const { + assert(DefIdx < SC->NumWriteLatencyEntries && + "MachineModel does not specify a WriteResource for DefIdx"); + + return &WriteLatencyTable[SC->WriteLatencyIdx + DefIdx]; + } + + int getReadAdvanceCycles(const MCSchedClassDesc *SC, unsigned UseIdx, + unsigned WriteResID) const { + // TODO: The number of read advance entries in a class can be significant + // (~50). Consider compressing the WriteID into a dense ID of those that are + // used by ReadAdvance and representing them as a bitset. + for (const MCReadAdvanceEntry *I = &ReadAdvanceTable[SC->ReadAdvanceIdx], + *E = I + SC->NumReadAdvanceEntries; I != E; ++I) { + if (I->UseIdx < UseIdx) + continue; + if (I->UseIdx > UseIdx) + break; + // Find the first WriteResIdx match, which has the highest cycle count. + if (!I->WriteResourceID || I->WriteResourceID == WriteResID) { + return I->Cycles; + } + } + return 0; + } + /// getInstrItineraryForCPU - Get scheduling itinerary of a CPU. /// InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const; + + /// Initialize an InstrItineraryData instance. + void initInstrItins(InstrItineraryData &InstrItins) const; }; } // End llvm namespace diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 4c9e7f5..fe92755 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -113,7 +113,7 @@ namespace llvm { return *Section; } - /// setSection - Mark the symbol as defined in the section \arg S. + /// setSection - Mark the symbol as defined in the section \p S. void setSection(const MCSection &S) { Section = &S; } /// setUndefined - Mark the symbol as undefined. @@ -133,7 +133,7 @@ namespace llvm { return Value != 0; } - /// getValue() - Get the value for variable symbols. + /// getVariableValue() - Get the value for variable symbols. const MCExpr *getVariableValue() const { assert(isVariable() && "Invalid accessor!"); IsUsed = true; @@ -149,7 +149,7 @@ namespace llvm { /// @} - /// print - Print the value to the stream \arg OS. + /// print - Print the value to the stream \p OS. void print(raw_ostream &OS) const; /// dump - Print the value to stderr. diff --git a/include/llvm/MC/MCTargetAsmLexer.h b/include/llvm/MC/MCTargetAsmLexer.h deleted file mode 100644 index d09fe04..0000000 --- a/include/llvm/MC/MCTargetAsmLexer.h +++ /dev/null @@ -1,89 +0,0 @@ -//===-- llvm/MC/MCTargetAsmLexer.h - Target Assembly Lexer ------*- 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_MCTARGETASMLEXER_H -#define LLVM_MC_MCTARGETASMLEXER_H - -#include "llvm/MC/MCParser/MCAsmLexer.h" - -namespace llvm { -class Target; - -/// MCTargetAsmLexer - Generic interface to target specific assembly lexers. -class MCTargetAsmLexer { - /// The current token - AsmToken CurTok; - - /// The location and description of the current error - SMLoc ErrLoc; - std::string Err; - - MCTargetAsmLexer(const MCTargetAsmLexer &) LLVM_DELETED_FUNCTION; - void operator=(const MCTargetAsmLexer &) LLVM_DELETED_FUNCTION; -protected: // Can only create subclasses. - MCTargetAsmLexer(const Target &); - - virtual AsmToken LexToken() = 0; - - void SetError(const SMLoc &errLoc, const std::string &err) { - ErrLoc = errLoc; - Err = err; - } - - /// TheTarget - The Target that this machine was created for. - const Target &TheTarget; - MCAsmLexer *Lexer; - -public: - virtual ~MCTargetAsmLexer(); - - const Target &getTarget() const { return TheTarget; } - - /// InstallLexer - Set the lexer to get tokens from lower-level lexer \arg L. - void InstallLexer(MCAsmLexer &L) { - Lexer = &L; - } - - MCAsmLexer *getLexer() { - return Lexer; - } - - /// Lex - Consume the next token from the input stream and return it. - const AsmToken &Lex() { - return CurTok = LexToken(); - } - - /// getTok - Get the current (last) lexed token. - const AsmToken &getTok() { - return CurTok; - } - - /// getErrLoc - Get the current error location - const SMLoc &getErrLoc() { - return ErrLoc; - } - - /// getErr - Get the current error string - const std::string &getErr() { - return Err; - } - - /// getKind - Get the kind of current token. - AsmToken::TokenKind getKind() const { return CurTok.getKind(); } - - /// is - Check if the current token has kind \arg K. - bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } - - /// isNot - Check if the current token has kind \arg K. - bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 709c2d2..483a80b 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -21,6 +21,39 @@ class MCParsedAsmOperand; class MCInst; template <typename T> class SmallVectorImpl; +enum AsmRewriteKind { + AOK_DotOperator, // Rewrite a dot operator expression as an immediate. + // E.g., [eax].foo.bar -> [eax].8 + AOK_Emit, // Rewrite _emit as .byte. + AOK_Imm, // Rewrite as $$N. + AOK_ImmPrefix, // Add $$ before a parsed Imm. + AOK_Input, // Rewrite in terms of $N. + AOK_Output, // Rewrite in terms of $N. + AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr). + AOK_Skip // Skip emission (e.g., offset/type operators). +}; + +struct AsmRewrite { + AsmRewriteKind Kind; + SMLoc Loc; + unsigned Len; + unsigned Val; +public: + AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, unsigned val = 0) + : Kind(kind), Loc(loc), Len(len), Val(val) {} +}; + +struct ParseInstructionInfo { + + SmallVectorImpl<AsmRewrite> *AsmRewrites; + + ParseInstructionInfo() : AsmRewrites(0) {} + ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites) + : AsmRewrites(rewrites) {} + + ~ParseInstructionInfo() {} +}; + /// MCTargetAsmParser - Generic interface to target specific assembly parsers. class MCTargetAsmParser : public MCAsmParserExtension { public: @@ -41,12 +74,26 @@ protected: // Can only create subclasses. /// AvailableFeatures - The current set of available features. unsigned AvailableFeatures; + /// ParsingInlineAsm - Are we parsing ms-style inline assembly? + bool ParsingInlineAsm; + + /// SemaCallback - The Sema callback implementation. Must be set when parsing + /// ms-style inline assembly. + MCAsmParserSemaCallback *SemaCallback; + public: virtual ~MCTargetAsmParser(); unsigned getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + bool isParsingInlineAsm () { return ParsingInlineAsm; } + void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } + + void setSemaCallback(MCAsmParserSemaCallback *Callback) { + SemaCallback = Callback; + } + virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; @@ -63,7 +110,8 @@ public: /// \param Operands [out] - The list of parsed operands, this returns /// ownership of them to the caller. /// \return True on failure. - virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, + virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0; /// ParseDirective - Parse a target specific assembler directive @@ -78,21 +126,9 @@ public: /// \param DirectiveID - the identifier token of the directive. virtual bool ParseDirective(AsmToken DirectiveID) = 0; - /// MatchInstruction - Recognize a series of operands of a parsed instruction - /// as an actual MCInst. This returns false on success and returns true on - /// failure to match. - /// - /// On failure, the target parser is responsible for emitting a diagnostic - /// explaining the match failure. - virtual bool - MatchInstruction(SMLoc IDLoc, unsigned &Kind, - SmallVectorImpl<MCParsedAsmOperand*> &Operands, - SmallVectorImpl<MCInst> &MCInsts, - unsigned &OrigErrorInfo, - bool matchingInlineAsm = false) { - OrigErrorInfo = ~0x0; - return true; - } + /// mnemonicIsValid - This returns true if this is a valid mnemonic and false + /// otherwise. + virtual bool mnemonicIsValid(StringRef Mnemonic) = 0; /// MatchAndEmitInstruction - Recognize a series of operands of a parsed /// instruction as an actual MCInst and emit it to the specified MCStreamer. @@ -101,9 +137,10 @@ public: /// On failure, the target parser is responsible for emitting a diagnostic /// explaining the match failure. virtual bool - MatchAndEmitInstruction(SMLoc IDLoc, + MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, SmallVectorImpl<MCParsedAsmOperand*> &Operands, - MCStreamer &Out) = 0; + MCStreamer &Out, unsigned &ErrorInfo, + bool MatchingInlineAsm) = 0; /// checkTargetMatchPredicate - Validate the instruction match against /// any complex target predicates not expressible via match classes. @@ -111,10 +148,8 @@ public: return Match_Success; } - virtual unsigned getMCInstOperandNum(unsigned Kind, MCInst &Inst, - const SmallVectorImpl<MCParsedAsmOperand*> &Operands, - unsigned OperandNum, - unsigned &NumMCOperands) = 0; + virtual void convertToMapAndConstraints(unsigned Kind, + const SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0; }; } // End llvm namespace diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index 8352ed1..a4e7301 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -14,8 +14,8 @@ #ifndef LLVM_MC_MCVALUE_H #define LLVM_MC_MCVALUE_H -#include "llvm/Support/DataTypes.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -46,7 +46,7 @@ public: /// isAbsolute - Is this an absolute (as opposed to relocatable) value. bool isAbsolute() const { return !SymA && !SymB; } - /// print - Print the value to the stream \arg OS. + /// print - Print the value to the stream \p OS. void print(raw_ostream &OS, const MCAsmInfo *MAI) const; /// dump - Print the value to stderr. diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index 7a0b1ff..11df574 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -11,6 +11,9 @@ #define LLVM_MC_MCWINCOFFOBJECTWRITER_H namespace llvm { + class MCObjectWriter; + class raw_ostream; + class MCWinCOFFObjectTargetWriter { const unsigned Machine; diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 87c5fd3..37ae03b 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -18,9 +18,9 @@ #ifndef LLVM_MC_SUBTARGETFEATURE_H #define LLVM_MC_SUBTARGETFEATURE_H -#include <vector> #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" +#include <vector> namespace llvm { class raw_ostream; @@ -95,10 +95,6 @@ public: const SubtargetFeatureKV *FeatureTable, size_t FeatureTableSize); - /// Get scheduling itinerary of a CPU. - const void *getItinerary(const StringRef CPU, - const SubtargetInfoKV *Table, size_t TableSize); - /// Print feature string. void print(raw_ostream &OS) const; diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 358b27a..8046efd 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -14,8 +14,8 @@ #ifndef LLVM_OBJECT_ARCHIVE_H #define LLVM_OBJECT_ARCHIVE_H -#include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Object/Binary.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -122,6 +122,16 @@ public: Archive(MemoryBuffer *source, error_code &ec); + enum Kind { + K_GNU, + K_BSD, + K_COFF + }; + + Kind kind() const { + return Format; + } + child_iterator begin_children(bool skip_internal = true) const; child_iterator end_children() const; @@ -129,14 +139,17 @@ public: symbol_iterator end_symbols() const; // Cast methods. - static inline bool classof(Archive const *v) { return true; } static inline bool classof(Binary const *v) { return v->isArchive(); } + // check if a symbol is in the archive + child_iterator findSym(StringRef name) const; + private: child_iterator SymbolTable; child_iterator StringTable; + Kind Format; }; } diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index befe812..d555de3 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -26,8 +26,8 @@ namespace object { class Binary { private: - Binary(); // = delete - Binary(const Binary &other); // = delete + Binary() LLVM_DELETED_FUNCTION; + Binary(const Binary &other) LLVM_DELETED_FUNCTION; unsigned int TypeID; @@ -64,7 +64,6 @@ public: // Cast methods. unsigned int getType() const { return TypeID; } - static inline bool classof(const Binary *v) { return true; } // Convenience methods bool isObject() const { diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 967420e..6f42d76 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -116,6 +116,7 @@ protected: 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 getSectionNext(DataRefImpl Sec, SectionRef &Res) const; virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; @@ -128,6 +129,7 @@ protected: virtual error_code isSectionBSS(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 isSectionRequiredForExecution(DataRefImpl Sec, bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, @@ -197,7 +199,6 @@ public: static inline bool classof(const Binary *v) { return v->isCOFF(); } - static inline bool classof(const COFFObjectFile *v) { return true; } }; } diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 9c4afed..aa26d17 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -14,11 +14,11 @@ #ifndef LLVM_OBJECT_ELF_H #define LLVM_OBJECT_ELF_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/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" @@ -35,6 +35,14 @@ namespace llvm { namespace object { +using support::endianness; + +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 inline std::pair<unsigned char, unsigned char> getElfArchType(MemoryBuffer *Object) { @@ -45,69 +53,78 @@ getElfArchType(MemoryBuffer *Object) { } // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -template<support::endianness target_endianness> +template<endianness target_endianness, std::size_t max_alignment> struct ELFDataTypeTypedefHelperCommon { typedef support::detail::packed_endian_specific_integral - <uint16_t, target_endianness, support::aligned> Elf_Half; + <uint16_t, target_endianness, + MaximumAlignment<uint16_t, max_alignment>::value> Elf_Half; typedef support::detail::packed_endian_specific_integral - <uint32_t, target_endianness, support::aligned> Elf_Word; + <uint32_t, target_endianness, + MaximumAlignment<uint32_t, max_alignment>::value> Elf_Word; typedef support::detail::packed_endian_specific_integral - <int32_t, target_endianness, support::aligned> Elf_Sword; + <int32_t, target_endianness, + MaximumAlignment<int32_t, max_alignment>::value> Elf_Sword; typedef support::detail::packed_endian_specific_integral - <uint64_t, target_endianness, support::aligned> Elf_Xword; + <uint64_t, target_endianness, + MaximumAlignment<uint64_t, max_alignment>::value> Elf_Xword; typedef support::detail::packed_endian_specific_integral - <int64_t, target_endianness, support::aligned> Elf_Sxword; + <int64_t, target_endianness, + MaximumAlignment<int64_t, max_alignment>::value> Elf_Sxword; }; -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct ELFDataTypeTypedefHelper; /// ELF 32bit types. -template<support::endianness target_endianness> -struct ELFDataTypeTypedefHelper<target_endianness, false> - : ELFDataTypeTypedefHelperCommon<target_endianness> { +template<endianness target_endianness, std::size_t max_alignment> +struct ELFDataTypeTypedefHelper<target_endianness, max_alignment, false> + : ELFDataTypeTypedefHelperCommon<target_endianness, max_alignment> { typedef uint32_t value_type; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, support::aligned> Elf_Addr; + <value_type, target_endianness, + MaximumAlignment<value_type, max_alignment>::value> Elf_Addr; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, support::aligned> Elf_Off; + <value_type, target_endianness, + MaximumAlignment<value_type, max_alignment>::value> Elf_Off; }; /// ELF 64bit types. -template<support::endianness target_endianness> -struct ELFDataTypeTypedefHelper<target_endianness, true> - : ELFDataTypeTypedefHelperCommon<target_endianness>{ +template<endianness target_endianness, std::size_t max_alignment> +struct ELFDataTypeTypedefHelper<target_endianness, max_alignment, true> + : ELFDataTypeTypedefHelperCommon<target_endianness, max_alignment>{ typedef uint64_t value_type; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, support::aligned> Elf_Addr; + <value_type, target_endianness, + MaximumAlignment<value_type, max_alignment>::value> Elf_Addr; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, support::aligned> Elf_Off; + <value_type, target_endianness, + MaximumAlignment<value_type, max_alignment>::value> Elf_Off; }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword; +#define LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) \ +typedef typename ELFDataTypeTypedefHelper \ + <target_endianness, max_alignment, is64Bits>::Elf_Addr Elf_Addr; \ +typedef typename ELFDataTypeTypedefHelper \ + <target_endianness, max_alignment, is64Bits>::Elf_Off Elf_Off; \ +typedef typename ELFDataTypeTypedefHelper \ + <target_endianness, max_alignment, is64Bits>::Elf_Half Elf_Half; \ +typedef typename ELFDataTypeTypedefHelper \ + <target_endianness, max_alignment, is64Bits>::Elf_Word Elf_Word; \ +typedef typename ELFDataTypeTypedefHelper \ + <target_endianness, max_alignment, is64Bits>::Elf_Sword Elf_Sword; \ +typedef typename ELFDataTypeTypedefHelper \ + <target_endianness, max_alignment, is64Bits>::Elf_Xword Elf_Xword; \ +typedef typename ELFDataTypeTypedefHelper \ + <target_endianness, max_alignment, is64Bits>::Elf_Sxword Elf_Sxword; // Section header. -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct Elf_Shdr_Base; -template<support::endianness target_endianness> -struct Elf_Shdr_Base<target_endianness, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Shdr_Base<target_endianness, max_alignment, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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_*) @@ -120,9 +137,9 @@ struct Elf_Shdr_Base<target_endianness, false> { Elf_Word sh_entsize; // Size of records contained within the section }; -template<support::endianness target_endianness> -struct Elf_Shdr_Base<target_endianness, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Shdr_Base<target_endianness, max_alignment, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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_*) @@ -135,10 +152,11 @@ struct Elf_Shdr_Base<target_endianness, true> { Elf_Xword sh_entsize; // Size of records contained within the section }; -template<support::endianness target_endianness, bool is64Bits> -struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { - using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize; - using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size; +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +struct Elf_Shdr_Impl + : Elf_Shdr_Base<target_endianness, max_alignment, is64Bits> { + using Elf_Shdr_Base<target_endianness, max_alignment, is64Bits>::sh_entsize; + using Elf_Shdr_Base<target_endianness, max_alignment, is64Bits>::sh_size; /// @brief Get the number of entities this section contains if it has any. unsigned getEntityCount() const { @@ -148,12 +166,14 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { } }; -template<support::endianness target_endianness, bool is64Bits> +template< endianness target_endianness + , std::size_t max_alignment + , bool is64Bits> struct Elf_Sym_Base; -template<support::endianness target_endianness> -struct Elf_Sym_Base<target_endianness, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Sym_Base<target_endianness, max_alignment, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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 @@ -162,9 +182,9 @@ struct Elf_Sym_Base<target_endianness, false> { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template<support::endianness target_endianness> -struct Elf_Sym_Base<target_endianness, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Sym_Base<target_endianness, max_alignment, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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 @@ -173,9 +193,10 @@ struct Elf_Sym_Base<target_endianness, true> { Elf_Xword st_size; // Size of the symbol }; -template<support::endianness target_endianness, bool is64Bits> -struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { - using Elf_Sym_Base<target_endianness, is64Bits>::st_info; +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +struct Elf_Sym_Impl + : Elf_Sym_Base<target_endianness, max_alignment, is64Bits> { + using Elf_Sym_Base<target_endianness, max_alignment, is64Bits>::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: @@ -190,21 +211,22 @@ struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { /// 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<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) }; -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> 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<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) - typedef Elf_Verdaux_Impl<target_endianness, is64Bits> Elf_Verdaux; + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + typedef + Elf_Verdaux_Impl<target_endianness, max_alignment, is64Bits> 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 @@ -221,18 +243,18 @@ struct Elf_Verdef_Impl { /// 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<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) 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<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) 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) @@ -242,9 +264,9 @@ struct Elf_Verneed_Impl { /// 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<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) 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 @@ -254,12 +276,12 @@ struct Elf_Vernaux_Impl { /// Elf_Dyn_Base: This structure matches the form of entries in the dynamic /// table section (.dynamic) look like. -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct Elf_Dyn_Base; -template<support::endianness target_endianness> -struct Elf_Dyn_Base<target_endianness, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Dyn_Base<target_endianness, max_alignment, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -267,9 +289,9 @@ struct Elf_Dyn_Base<target_endianness, false> { } d_un; }; -template<support::endianness target_endianness> -struct Elf_Dyn_Base<target_endianness, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Dyn_Base<target_endianness, max_alignment, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -278,24 +300,24 @@ struct Elf_Dyn_Base<target_endianness, true> { }; /// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. -template<support::endianness target_endianness, bool is64Bits> -struct Elf_Dyn_Impl : Elf_Dyn_Base<target_endianness, is64Bits> { - using Elf_Dyn_Base<target_endianness, is64Bits>::d_tag; - using Elf_Dyn_Base<target_endianness, is64Bits>::d_un; +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +struct Elf_Dyn_Impl : Elf_Dyn_Base<target_endianness, max_alignment, is64Bits> { + using Elf_Dyn_Base<target_endianness, max_alignment, is64Bits>::d_tag; + using Elf_Dyn_Base<target_endianness, max_alignment, is64Bits>::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; } }; -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> class ELFObjectFile; // DynRefImpl: Reference to an entry in the dynamic table // This is an ELF-specific interface. -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> class DynRefImpl { - typedef Elf_Dyn_Impl<target_endianness, is64Bits> Elf_Dyn; - typedef ELFObjectFile<target_endianness, is64Bits> OwningType; + typedef Elf_Dyn_Impl<target_endianness, max_alignment, is64Bits> Elf_Dyn; + typedef ELFObjectFile<target_endianness, max_alignment, is64Bits> OwningType; DataRefImpl DynPimpl; const OwningType *OwningObject; @@ -317,66 +339,72 @@ public: }; // Elf_Rel: Elf Relocation -template<support::endianness target_endianness, bool is64Bits, bool isRela> +template< endianness target_endianness + , std::size_t max_alignment + , bool is64Bits + , bool isRela> struct Elf_Rel_Base; -template<support::endianness target_endianness> -struct Elf_Rel_Base<target_endianness, false, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Rel_Base<target_endianness, max_alignment, false, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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 }; -template<support::endianness target_endianness> -struct Elf_Rel_Base<target_endianness, true, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Rel_Base<target_endianness, max_alignment, true, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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 }; -template<support::endianness target_endianness> -struct Elf_Rel_Base<target_endianness, false, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Rel_Base<target_endianness, max_alignment, false, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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 }; -template<support::endianness target_endianness> -struct Elf_Rel_Base<target_endianness, true, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Rel_Base<target_endianness, max_alignment, true, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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. }; -template<support::endianness target_endianness, bool is64Bits, bool isRela> +template< endianness target_endianness + , std::size_t max_alignment + , bool is64Bits + , bool isRela> struct Elf_Rel_Impl; -template<support::endianness target_endianness, bool isRela> -struct Elf_Rel_Impl<target_endianness, true, isRela> - : Elf_Rel_Base<target_endianness, true, isRela> { - using Elf_Rel_Base<target_endianness, true, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, true) +template<endianness target_endianness, std::size_t max_alignment, bool isRela> +struct Elf_Rel_Impl<target_endianness, max_alignment, true, isRela> + : Elf_Rel_Base<target_endianness, max_alignment, true, isRela> { + using Elf_Rel_Base<target_endianness, max_alignment, true, isRela>::r_info; + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: - uint64_t getSymbol() const { return (r_info >> 32); } - unsigned char getType() const { - return (unsigned char) (r_info & 0xffffffffL); + uint32_t getSymbol() const { return (uint32_t) (r_info >> 32); } + uint32_t getType() const { + return (uint32_t) (r_info & 0xffffffffL); } - void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint64_t s, unsigned char t) { - r_info = (s << 32) + (t&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) { + r_info = ((uint64_t)s << 32) + (t&0xffffffffL); } }; -template<support::endianness target_endianness, bool isRela> -struct Elf_Rel_Impl<target_endianness, false, isRela> - : Elf_Rel_Base<target_endianness, false, isRela> { - using Elf_Rel_Base<target_endianness, false, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, false) +template<endianness target_endianness, std::size_t max_alignment, bool isRela> +struct Elf_Rel_Impl<target_endianness, max_alignment, false, isRela> + : Elf_Rel_Base<target_endianness, max_alignment, false, isRela> { + using Elf_Rel_Base<target_endianness, max_alignment, false, isRela>::r_info; + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: @@ -389,9 +417,9 @@ struct Elf_Rel_Impl<target_endianness, false, isRela> } }; -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) 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_*) @@ -414,22 +442,59 @@ struct Elf_Ehdr_Impl { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +struct Elf_Phdr_Impl; + +template<endianness target_endianness, std::size_t max_alignment> +struct Elf_Phdr_Impl<target_endianness, max_alignment, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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 target_endianness, std::size_t max_alignment> +struct Elf_Phdr_Impl<target_endianness, max_alignment, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, 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<endianness target_endianness, std::size_t max_alignment, bool is64Bits> class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) - - typedef Elf_Ehdr_Impl<target_endianness, is64Bits> Elf_Ehdr; - typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; - typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; - typedef Elf_Dyn_Impl<target_endianness, is64Bits> Elf_Dyn; - typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; - typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; - typedef Elf_Verdef_Impl<target_endianness, is64Bits> Elf_Verdef; - typedef Elf_Verdaux_Impl<target_endianness, is64Bits> Elf_Verdaux; - typedef Elf_Verneed_Impl<target_endianness, is64Bits> Elf_Verneed; - typedef Elf_Vernaux_Impl<target_endianness, is64Bits> Elf_Vernaux; - typedef Elf_Versym_Impl<target_endianness, is64Bits> Elf_Versym; - typedef DynRefImpl<target_endianness, is64Bits> DynRef; + LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + + typedef Elf_Ehdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Ehdr; + typedef Elf_Shdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Shdr; + typedef Elf_Sym_Impl<target_endianness, max_alignment, is64Bits> Elf_Sym; + typedef Elf_Dyn_Impl<target_endianness, max_alignment, is64Bits> Elf_Dyn; + typedef Elf_Phdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Phdr; + typedef + Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, false> Elf_Rel; + typedef + Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, true> Elf_Rela; + typedef + Elf_Verdef_Impl<target_endianness, max_alignment, is64Bits> Elf_Verdef; + typedef + Elf_Verdaux_Impl<target_endianness, max_alignment, is64Bits> Elf_Verdaux; + typedef + Elf_Verneed_Impl<target_endianness, max_alignment, is64Bits> Elf_Verneed; + typedef + Elf_Vernaux_Impl<target_endianness, max_alignment, is64Bits> Elf_Vernaux; + typedef + Elf_Versym_Impl<target_endianness, max_alignment, is64Bits> Elf_Versym; + typedef DynRefImpl<target_endianness, max_alignment, is64Bits> DynRef; typedef content_iterator<DynRef> dyn_iterator; protected: @@ -464,6 +529,59 @@ private: // This is set the first time getLoadName is called. mutable const char *dt_soname; +public: + /// \brief Iterate over constant sized entities. + template<class EntT> + class ELFEntityIterator { + public: + typedef void difference_type; + typedef EntT value_type; + typedef std::forward_iterator_tag iterator_category; + typedef value_type &reference; + typedef value_type *pointer; + + /// \brief Default construct iterator. + ELFEntityIterator() : EntitySize(0), Current(0) {} + ELFEntityIterator(uint64_t EntSize, const char *Start) + : EntitySize(EntSize) + , Current(Start) {} + + reference operator *() { + assert(Current && "Attempted to dereference an invalid iterator!"); + return *reinterpret_cast<pointer>(Current); + } + + pointer operator ->() { + assert(Current && "Attempted to dereference an invalid iterator!"); + return reinterpret_cast<pointer>(Current); + } + + bool operator ==(const ELFEntityIterator &Other) { + return Current == Other.Current; + } + + bool operator !=(const ELFEntityIterator &Other) { + return !(*this == Other); + } + + ELFEntityIterator &operator ++() { + assert(Current && "Attempted to increment an invalid iterator!"); + Current += EntitySize; + return *this; + } + + ELFEntityIterator operator ++(int) { + ELFEntityIterator Tmp = *this; + ++*this; + return Tmp; + } + + private: + const uint64_t EntitySize; + const char *Current; + }; + +private: // 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> { @@ -529,6 +647,7 @@ public: 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; protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; @@ -540,8 +659,9 @@ protected: 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; - friend class DynRefImpl<target_endianness, is64Bits>; + friend class DynRefImpl<target_endianness, max_alignment, is64Bits>; virtual error_code getDynNext(DataRefImpl DynData, DynRef &Result) const; virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; @@ -560,6 +680,7 @@ protected: 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; @@ -599,6 +720,44 @@ public: virtual dyn_iterator begin_dynamic_table() const; virtual dyn_iterator end_dynamic_table() const; + typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter; + typedef ELFEntityIterator<const Elf_Rel> Elf_Rel_Iter; + + Elf_Rela_Iter beginELFRela(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_Rel_Iter beginELFRel(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)); + } + + /// \brief Iterate over program header table. + typedef ELFEntityIterator<const Elf_Phdr> Elf_Phdr_Iter; + + Elf_Phdr_Iter begin_program_headers() const { + return Elf_Phdr_Iter(Header->e_phentsize, + (const char*)base() + Header->e_phoff); + } + + Elf_Phdr_Iter end_program_headers() const { + return Elf_Phdr_Iter(Header->e_phentsize, + (const char*)base() + + Header->e_phoff + + (Header->e_phnum * Header->e_phentsize)); + } + virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; virtual StringRef getObjectType() const { return "ELF"; } @@ -613,6 +772,7 @@ public: 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; } @@ -620,13 +780,12 @@ public: return v->getType() == getELFType(target_endianness == support::little, is64Bits); } - static inline bool classof(const ELFObjectFile *v) { return true; } }; // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. -template<support::endianness target_endianness, bool is64Bits> -void ELFObjectFile<target_endianness, is64Bits>:: +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: 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 @@ -651,8 +810,8 @@ void ELFObjectFile<target_endianness, is64Bits>:: // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. -template<support::endianness target_endianness, bool is64Bits> -void ELFObjectFile<target_endianness, is64Bits>:: +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: 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 @@ -684,8 +843,9 @@ void ELFObjectFile<target_endianness, is64Bits>:: } } -template<support::endianness target_endianness, bool is64Bits> -void ELFObjectFile<target_endianness, is64Bits>::LoadVersionMap() const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +void ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) return; @@ -706,8 +866,8 @@ void ELFObjectFile<target_endianness, is64Bits>::LoadVersionMap() const { LoadVersionNeeds(dot_gnu_version_r_sec); } -template<support::endianness target_endianness, bool is64Bits> -void ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +void ELFObjectFile<target_endianness, max_alignment, is64Bits> ::validateSymbol(DataRefImpl Symb) const { const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; @@ -725,8 +885,8 @@ void ELFObjectFile<target_endianness, is64Bits> report_fatal_error("Symb must point to a valid symbol!"); } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolNext(DataRefImpl Symb, SymbolRef &Result) const { validateSymbol(Symb); @@ -753,8 +913,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolName(DataRefImpl Symb, StringRef &Result) const { validateSymbol(Symb); @@ -762,8 +922,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolVersion(SymbolRef SymRef, StringRef &Version, bool &IsDefault) const { @@ -774,17 +934,18 @@ error_code ELFObjectFile<target_endianness, is64Bits> Version, IsDefault); } -template<support::endianness target_endianness, bool is64Bits> -ELF::Elf64_Word ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +ELF::Elf64_Word ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolTableIndex(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return ExtendedSymbolTable.lookup(symb); return symb->st_shndx; } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * -ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Shdr * +ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSection(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); @@ -793,23 +954,36 @@ ELFObjectFile<target_endianness, is64Bits> return getSection(symb->st_shndx); } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * -ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Shdr * +ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getElfSection(section_iterator &It) const { llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); return reinterpret_cast<const Elf_Shdr *>(ShdrRef.p); } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * -ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Sym * +ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getElfSymbol(symbol_iterator &It) const { return getSymbol(It->getRawDataRefImpl()); } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Sym * +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getElfSymbol(uint32_t index) const { + DataRefImpl SymbolData; + SymbolData.d.a = index; + SymbolData.d.b = 1; + return getSymbol(SymbolData); +} + +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolFileOffset(DataRefImpl Symb, uint64_t &Result) const { validateSymbol(Symb); @@ -843,8 +1017,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> } } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolAddress(DataRefImpl Symb, uint64_t &Result) const { validateSymbol(Symb); @@ -868,7 +1042,18 @@ error_code ELFObjectFile<target_endianness, is64Bits> case ELF::STT_FUNC: case ELF::STT_OBJECT: case ELF::STT_NOTYPE: - Result = symb->st_value + (Section ? Section->sh_addr : 0); + bool IsRelocatable; + switch(Header->e_type) { + case ELF::ET_EXEC: + case ELF::ET_DYN: + IsRelocatable = false; + break; + default: + IsRelocatable = true; + } + Result = symb->st_value; + if (IsRelocatable && Section != 0) + Result += Section->sh_addr; return object_error::success; default: Result = UnknownAddressOrSize; @@ -876,8 +1061,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> } } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolSize(DataRefImpl Symb, uint64_t &Result) const { validateSymbol(Symb); @@ -888,8 +1073,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolNMTypeChar(DataRefImpl Symb, char &Result) const { validateSymbol(Symb); @@ -953,8 +1138,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolType(DataRefImpl Symb, SymbolRef::Type &Result) const { validateSymbol(Symb); @@ -985,8 +1170,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolFlags(DataRefImpl Symb, uint32_t &Result) const { validateSymbol(Symb); @@ -1020,8 +1205,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { validateSymbol(Symb); @@ -1037,8 +1222,18 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + Val = symb->st_value; + return object_error::success; +} + +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); sec += Header->e_shentsize; @@ -1047,8 +1242,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionName(DataRefImpl Sec, StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1056,8 +1251,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionAddress(DataRefImpl Sec, uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1065,8 +1260,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionSize(DataRefImpl Sec, uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1074,8 +1269,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionContents(DataRefImpl Sec, StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1084,8 +1279,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionContents(const Elf_Shdr *Sec, StringRef &Result) const { const char *start = (const char*)base() + Sec->sh_offset; @@ -1093,8 +1288,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionAlignment(DataRefImpl Sec, uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1102,8 +1297,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::isSectionText(DataRefImpl Sec, bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1114,8 +1309,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::isSectionData(DataRefImpl Sec, bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1127,8 +1322,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::isSectionBSS(DataRefImpl Sec, bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1140,8 +1335,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::isSectionRequiredForExecution(DataRefImpl Sec, bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1152,8 +1347,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::isSectionVirtual(DataRefImpl Sec, bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1164,21 +1359,31 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits>::isSectionZeroInit(DataRefImpl Sec, +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::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. - if (sec->sh_flags & ELF::SHT_NOBITS) - Result = true; - else + Result = sec->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::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<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { @@ -1187,8 +1392,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -relocation_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl RelData; const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1201,8 +1406,8 @@ relocation_iterator ELFObjectFile<target_endianness, is64Bits> return relocation_iterator(RelocationRef(RelData, this)); } -template<support::endianness target_endianness, bool is64Bits> -relocation_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionRelEnd(DataRefImpl Sec) const { DataRefImpl RelData; const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1219,8 +1424,8 @@ relocation_iterator ELFObjectFile<target_endianness, is64Bits> } // Relocations -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getRelocationNext(DataRefImpl Rel, RelocationRef &Result) const { ++Rel.w.c; @@ -1248,8 +1453,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Result) const { uint32_t symbolIdx; @@ -1276,8 +1481,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getRelocationAddress(DataRefImpl Rel, uint64_t &Result) const { uint64_t offset; @@ -1299,8 +1504,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getRelocationOffset(DataRefImpl Rel, uint64_t &Result) const { uint64_t offset; @@ -1322,8 +1527,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getRelocationType(DataRefImpl Rel, uint64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); @@ -1345,12 +1550,12 @@ error_code ELFObjectFile<target_endianness, is64Bits> #define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ case ELF::enum: res = #enum; break; -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); - uint8_t type; + uint32_t type; StringRef res; switch (sec->sh_type) { default : @@ -1687,8 +1892,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> #undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getRelocationAdditionalInfo(DataRefImpl Rel, int64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); @@ -1706,8 +1911,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> } } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); @@ -1777,8 +1982,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> } // Verify that the last byte in the string table in a null. -template<support::endianness target_endianness, bool is64Bits> -void ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +void ELFObjectFile<target_endianness, max_alignment, is64Bits> ::VerifyStrTab(const Elf_Shdr *sh) const { const char *strtab = (const char*)base() + sh->sh_offset; if (strtab[sh->sh_size - 1] != 0) @@ -1786,9 +1991,9 @@ void ELFObjectFile<target_endianness, is64Bits> report_fatal_error("String table must end with a null terminator!"); } -template<support::endianness target_endianness, bool is64Bits> -ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object - , error_code &ec) +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::ELFObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(getELFType(target_endianness == support::little, is64Bits), Object, ec) , isDyldELFObject(false) @@ -1947,8 +2152,23 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object } } -template<support::endianness target_endianness, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, is64Bits> +// Get the symbol table index in the symtab section given a symbol +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getSymbolIndex(const Elf_Sym *Sym) const { + assert(SymbolTableSections.size() == 1 && "Only one symbol table supported!"); + const Elf_Shdr *SymTab = *SymbolTableSections.begin(); + uintptr_t SymLoc = uintptr_t(Sym); + uintptr_t SymTabLoc = uintptr_t(base() + SymTab->sh_offset); + assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); + uint64_t SymOffset = SymLoc - SymTabLoc; + assert(SymOffset % SymTab->sh_entsize == 0 && + "Symbol not multiple of symbol size!"); + return SymOffset / SymTab->sh_entsize; +} + +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::begin_symbols() const { DataRefImpl SymbolData; if (SymbolTableSections.size() <= 1) { @@ -1961,8 +2181,8 @@ symbol_iterator ELFObjectFile<target_endianness, is64Bits> return symbol_iterator(SymbolRef(SymbolData, this)); } -template<support::endianness target_endianness, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::end_symbols() const { DataRefImpl SymbolData; SymbolData.d.a = std::numeric_limits<uint32_t>::max(); @@ -1970,8 +2190,8 @@ symbol_iterator ELFObjectFile<target_endianness, is64Bits> return symbol_iterator(SymbolRef(SymbolData, this)); } -template<support::endianness target_endianness, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::begin_dynamic_symbols() const { DataRefImpl SymbolData; if (SymbolTableSections[0] == NULL) { @@ -1984,8 +2204,8 @@ symbol_iterator ELFObjectFile<target_endianness, is64Bits> return symbol_iterator(SymbolRef(SymbolData, this)); } -template<support::endianness target_endianness, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::end_dynamic_symbols() const { DataRefImpl SymbolData; SymbolData.d.a = std::numeric_limits<uint32_t>::max(); @@ -1993,16 +2213,16 @@ symbol_iterator ELFObjectFile<target_endianness, is64Bits> return symbol_iterator(SymbolRef(SymbolData, this)); } -template<support::endianness target_endianness, bool is64Bits> -section_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +section_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::begin_sections() const { DataRefImpl ret; ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); return section_iterator(SectionRef(ret, this)); } -template<support::endianness target_endianness, bool is64Bits> -section_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +section_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::end_sections() const { DataRefImpl ret; ret.p = reinterpret_cast<intptr_t>(base() @@ -2011,9 +2231,10 @@ section_iterator ELFObjectFile<target_endianness, is64Bits> return section_iterator(SectionRef(ret, this)); } -template<support::endianness target_endianness, bool is64Bits> -typename ELFObjectFile<target_endianness, is64Bits>::dyn_iterator -ELFObjectFile<target_endianness, is64Bits>::begin_dynamic_table() const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +typename ELFObjectFile<target_endianness, max_alignment, is64Bits>::dyn_iterator +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::begin_dynamic_table() const { DataRefImpl DynData; if (dot_dynamic_sec == NULL || dot_dynamic_sec->sh_size == 0) { DynData.d.a = std::numeric_limits<uint32_t>::max(); @@ -2023,17 +2244,17 @@ ELFObjectFile<target_endianness, is64Bits>::begin_dynamic_table() const { return dyn_iterator(DynRef(DynData, this)); } -template<support::endianness target_endianness, bool is64Bits> -typename ELFObjectFile<target_endianness, is64Bits>::dyn_iterator -ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +typename ELFObjectFile<target_endianness, max_alignment, is64Bits>::dyn_iterator +ELFObjectFile<target_endianness, max_alignment, is64Bits> ::end_dynamic_table() const { DataRefImpl DynData; DynData.d.a = std::numeric_limits<uint32_t>::max(); return dyn_iterator(DynRef(DynData, this)); } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getDynNext(DataRefImpl DynData, DynRef &Result) const { ++DynData.d.a; @@ -2048,9 +2269,9 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> StringRef -ELFObjectFile<target_endianness, is64Bits>::getLoadName() const { +ELFObjectFile<target_endianness, max_alignment, is64Bits>::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry dyn_iterator it = begin_dynamic_table(); @@ -2074,8 +2295,8 @@ ELFObjectFile<target_endianness, is64Bits>::getLoadName() const { return dt_soname; } -template<support::endianness target_endianness, bool is64Bits> -library_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +library_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::begin_libraries_needed() const { // Find the first DT_NEEDED entry dyn_iterator i = begin_dynamic_table(); @@ -2092,8 +2313,8 @@ library_iterator ELFObjectFile<target_endianness, is64Bits> return library_iterator(LibraryRef(i->getRawDataRefImpl(), this)); } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getLibraryNext(DataRefImpl Data, LibraryRef &Result) const { // Use the same DataRefImpl format as DynRef. @@ -2121,8 +2342,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getLibraryPath(DataRefImpl Data, StringRef &Res) const { dyn_iterator i = dyn_iterator(DynRef(Data, this)); if (i == end_dynamic_table()) @@ -2142,21 +2363,22 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -library_iterator ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +library_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> ::end_libraries_needed() const { dyn_iterator e = end_dynamic_table(); // Use the same DataRefImpl format as DynRef. return library_iterator(LibraryRef(e->getRawDataRefImpl(), this)); } -template<support::endianness target_endianness, bool is64Bits> -uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +uint8_t ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getBytesInAddress() const { return is64Bits ? 8 : 4; } -template<support::endianness target_endianness, bool is64Bits> -StringRef ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +StringRef ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getFileFormatName() const { switch(Header->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: @@ -2178,6 +2400,8 @@ StringRef ELFObjectFile<target_endianness, is64Bits> return "ELF64-i386"; case ELF::EM_X86_64: return "ELF64-x86-64"; + case ELF::EM_PPC64: + return "ELF64-ppc64"; default: return "ELF64-unknown"; } @@ -2187,8 +2411,9 @@ StringRef ELFObjectFile<target_endianness, is64Bits> } } -template<support::endianness target_endianness, bool is64Bits> -unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +unsigned ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getArch() const { switch(Header->e_machine) { case ELF::EM_386: return Triple::x86; @@ -2201,13 +2426,16 @@ unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { case ELF::EM_MIPS: return (target_endianness == support::little) ? Triple::mipsel : Triple::mips; + case ELF::EM_PPC64: + return Triple::ppc64; default: return Triple::UnknownArch; } } -template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits>::getNumSections() const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getNumSections() const { assert(Header && "Header not initialized!"); if (Header->e_shnum == ELF::SHN_UNDEF) { assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); @@ -2216,9 +2444,10 @@ uint64_t ELFObjectFile<target_endianness, is64Bits>::getNumSections() const { return Header->e_shnum; } -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> uint64_t -ELFObjectFile<target_endianness, is64Bits>::getStringTableIndex() const { +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getStringTableIndex() const { if (Header->e_shnum == ELF::SHN_UNDEF) { if (Header->e_shstrndx == ELF::SHN_HIRESERVE) return SectionHeaderTable->sh_link; @@ -2228,53 +2457,62 @@ ELFObjectFile<target_endianness, is64Bits>::getStringTableIndex() const { return Header->e_shstrndx; } - -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> template<typename T> inline const T * -ELFObjectFile<target_endianness, is64Bits>::getEntry(uint16_t Section, - uint32_t Entry) const { +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getEntry(uint16_t Section, uint32_t Entry) const { return getEntry<T>(getSection(Section), Entry); } -template<support::endianness target_endianness, bool is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> template<typename T> inline const T * -ELFObjectFile<target_endianness, is64Bits>::getEntry(const Elf_Shdr * Section, - uint32_t Entry) const { +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { return reinterpret_cast<const T *>( base() + Section->sh_offset + (Entry * Section->sh_entsize)); } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * -ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Sym * +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getSymbol(DataRefImpl Symb) const { return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a); } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Dyn * -ELFObjectFile<target_endianness, is64Bits>::getDyn(DataRefImpl DynData) const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Dyn * +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getDyn(DataRefImpl DynData) const { return getEntry<Elf_Dyn>(dot_dynamic_sec, DynData.d.a); } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel * -ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Rel * +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getRel(DataRefImpl Rel) const { return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c); } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela * -ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Rela * +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getRela(DataRefImpl Rela) const { return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c); } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * -ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Shdr * +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::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. @@ -2282,9 +2520,11 @@ ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const { return sec; } -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * -ELFObjectFile<target_endianness, is64Bits>::getSection(uint32_t index) const { +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::Elf_Shdr * +ELFObjectFile<target_endianness, max_alignment, is64Bits> + ::getSection(uint32_t index) const { if (index == 0) return 0; if (!SectionHeaderTable || index >= getNumSections()) @@ -2296,15 +2536,15 @@ ELFObjectFile<target_endianness, is64Bits>::getSection(uint32_t index) const { + (index * Header->e_shentsize)); } -template<support::endianness target_endianness, bool is64Bits> -const char *ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const char *ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getString(uint32_t section, ELF::Elf32_Word offset) const { return getString(getSection(section), offset); } -template<support::endianness target_endianness, bool is64Bits> -const char *ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +const char *ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getString(const Elf_Shdr *section, ELF::Elf32_Word offset) const { assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); @@ -2314,8 +2554,8 @@ const char *ELFObjectFile<target_endianness, is64Bits> return (const char *)base() + section->sh_offset + offset; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolName(const Elf_Shdr *section, const Elf_Sym *symb, StringRef &Result) const { @@ -2338,16 +2578,16 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSectionName(const Elf_Shdr *section, StringRef &Result) const { Result = StringRef(getString(dot_shstrtab_sec, section->sh_name)); return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> ::getSymbolVersion(const Elf_Shdr *section, const Elf_Sym *symb, StringRef &Version, @@ -2429,50 +2669,50 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } -template<support::endianness target_endianness, bool is64Bits> -inline DynRefImpl<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +inline DynRefImpl<target_endianness, max_alignment, is64Bits> ::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) : DynPimpl(DynP) , OwningObject(Owner) {} -template<support::endianness target_endianness, bool is64Bits> -inline bool DynRefImpl<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +inline bool DynRefImpl<target_endianness, max_alignment, is64Bits> ::operator==(const DynRefImpl &Other) const { return DynPimpl == Other.DynPimpl; } -template<support::endianness target_endianness, bool is64Bits> -inline bool DynRefImpl<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +inline bool DynRefImpl<target_endianness, max_alignment, is64Bits> ::operator <(const DynRefImpl &Other) const { return DynPimpl < Other.DynPimpl; } -template<support::endianness target_endianness, bool is64Bits> -inline error_code DynRefImpl<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +inline error_code DynRefImpl<target_endianness, max_alignment, is64Bits> ::getNext(DynRefImpl &Result) const { return OwningObject->getDynNext(DynPimpl, Result); } -template<support::endianness target_endianness, bool is64Bits> -inline int64_t DynRefImpl<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +inline int64_t DynRefImpl<target_endianness, max_alignment, is64Bits> ::getTag() const { return OwningObject->getDyn(DynPimpl)->d_tag; } -template<support::endianness target_endianness, bool is64Bits> -inline uint64_t DynRefImpl<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +inline uint64_t DynRefImpl<target_endianness, max_alignment, is64Bits> ::getVal() const { return OwningObject->getDyn(DynPimpl)->d_un.d_val; } -template<support::endianness target_endianness, bool is64Bits> -inline uint64_t DynRefImpl<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +inline uint64_t DynRefImpl<target_endianness, max_alignment, is64Bits> ::getPtr() const { return OwningObject->getDyn(DynPimpl)->d_un.d_ptr; } -template<support::endianness target_endianness, bool is64Bits> -inline DataRefImpl DynRefImpl<target_endianness, is64Bits> +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +inline DataRefImpl DynRefImpl<target_endianness, max_alignment, is64Bits> ::getRawDataRefImpl() const { return DynPimpl; } @@ -2484,23 +2724,23 @@ static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, StringRef &Version, bool &IsDefault) { // Little-endian 32-bit - if (const ELFObjectFile<support::little, false> *ELFObj = - dyn_cast<ELFObjectFile<support::little, false> >(Obj)) + if (const ELFObjectFile<support::little, 4, false> *ELFObj = + dyn_cast<ELFObjectFile<support::little, 4, false> >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 32-bit - if (const ELFObjectFile<support::big, false> *ELFObj = - dyn_cast<ELFObjectFile<support::big, false> >(Obj)) + if (const ELFObjectFile<support::big, 4, false> *ELFObj = + dyn_cast<ELFObjectFile<support::big, 4, false> >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Little-endian 64-bit - if (const ELFObjectFile<support::little, true> *ELFObj = - dyn_cast<ELFObjectFile<support::little, true> >(Obj)) + if (const ELFObjectFile<support::little, 8, true> *ELFObj = + dyn_cast<ELFObjectFile<support::little, 8, true> >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 64-bit - if (const ELFObjectFile<support::big, true> *ELFObj = - dyn_cast<ELFObjectFile<support::big, true> >(Obj)) + if (const ELFObjectFile<support::big, 8, true> *ELFObj = + dyn_cast<ELFObjectFile<support::big, 8, true> >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 0b73f94..ed7aabd 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -15,11 +15,11 @@ #ifndef LLVM_OBJECT_MACHO_H #define LLVM_OBJECT_MACHO_H -#include "llvm/Object/ObjectFile.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Object/MachOObject.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/SmallVector.h" namespace llvm { namespace object { @@ -44,12 +44,16 @@ public: virtual unsigned getArch() const; virtual StringRef getLoadName() const; - MachOObject *getObject() { return MachOObj; } + // In a MachO file, sections have a segment name. This is used in the .o + // files. They have a single segment, but this field specifies which segment + // a section should be put in in the final object. + error_code getSectionFinalSegmentName(DataRefImpl Sec, StringRef &Res) const; + + MachOObject *getObject() { return MachOObj.get(); } static inline bool classof(const Binary *v) { return v->isMachO(); } - static inline bool classof(const MachOObjectFile *v) { return true; } protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; @@ -62,6 +66,7 @@ protected: 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 getSectionNext(DataRefImpl Sec, SectionRef &Res) const; virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; @@ -76,6 +81,7 @@ protected: 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 DRI, DataRefImpl S, bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; @@ -103,7 +109,7 @@ protected: virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; private: - MachOObject *MachOObj; + OwningPtr<MachOObject> MachOObj; mutable uint32_t RegisteredStringTable; typedef SmallVector<DataRefImpl, 1> SectionList; SectionList Sections; diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index e4bfcc6..a17d58d 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -61,7 +61,10 @@ namespace mach { CSARM_V6 = 6, CSARM_V5TEJ = 7, CSARM_XSCALE = 8, - CSARM_V7 = 9 + CSARM_V7 = 9, + CSARM_V7F = 10, + CSARM_V7S = 11, + CSARM_V7K = 12 }; /// \brief PowerPC Machine Subtypes. @@ -234,6 +237,10 @@ namespace macho { /// @name Section Data /// @{ + enum SectionFlags { + SF_PureInstructions = 0x80000000 + }; + struct Section { char Name[16]; char SegmentName[16]; diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h index 86f150a..e32a85d 100644 --- a/include/llvm/Object/MachOObject.h +++ b/include/llvm/Object/MachOObject.h @@ -10,11 +10,11 @@ #ifndef LLVM_OBJECT_MACHOOBJECT_H #define LLVM_OBJECT_MACHOOBJECT_H -#include <string> #include "llvm/ADT/InMemoryStruct.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Object/MachOFormat.h" +#include <string> namespace llvm { diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 2ec656b..e63f554 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -14,8 +14,8 @@ #ifndef LLVM_OBJECT_OBJECT_FILE_H #define LLVM_OBJECT_OBJECT_FILE_H -#include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Object/Binary.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" @@ -76,13 +76,13 @@ public: } }; -inline bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { +inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { // Check bitwise identical. This is the only legal way to compare a union w/o // knowing which member is in use. return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; } -inline bool operator <(const DataRefImpl &a, const DataRefImpl &b) { +inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { // Check bitwise identical. This is the only legal way to compare a union w/o // knowing which member is in use. return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; @@ -144,7 +144,7 @@ public: SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); bool operator==(const SectionRef &Other) const; - bool operator <(const SectionRef &Other) const; + bool operator<(const SectionRef &Other) const; error_code getNext(SectionRef &Result) const; @@ -163,6 +163,7 @@ public: error_code isRequiredForExecution(bool &Result) const; error_code isVirtual(bool &Result) const; error_code isZeroInit(bool &Result) const; + error_code isReadOnlyData(bool &Result) const; error_code containsSymbol(SymbolRef S, bool &Result) const; @@ -207,11 +208,13 @@ public: SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); bool operator==(const SymbolRef &Other) const; - bool operator <(const SymbolRef &Other) const; + bool operator<(const SymbolRef &Other) const; error_code getNext(SymbolRef &Result) const; error_code getName(StringRef &Result) const; + /// Returns the symbol virtual address (i.e. address at which it will be + /// mapped). error_code getAddress(uint64_t &Result) const; error_code getFileOffset(uint64_t &Result) const; error_code getSize(uint64_t &Result) const; @@ -231,6 +234,9 @@ public: /// end_sections() if it is undefined or is an absolute symbol. error_code getSection(section_iterator &Result) const; + /// @brief Get value of the symbol in the symbol table. + error_code getValue(uint64_t &Val) const; + DataRefImpl getRawDataRefImpl() const; }; typedef content_iterator<SymbolRef> symbol_iterator; @@ -248,7 +254,7 @@ public: LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner); bool operator==(const LibraryRef &Other) const; - bool operator <(const LibraryRef &Other) const; + bool operator<(const LibraryRef &Other) const; error_code getNext(LibraryRef &Result) const; @@ -263,11 +269,11 @@ const uint64_t UnknownAddressOrSize = ~0ULL; /// ObjectFile - This class is the base class for all object file types. /// Concrete instances of this object are created by createObjectFile, which -/// figure out which type to create. +/// figures out which type to create. class ObjectFile : public Binary { virtual void anchor(); - ObjectFile(); // = delete - ObjectFile(const ObjectFile &other); // = delete + ObjectFile() LLVM_DELETED_FUNCTION; + ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec); @@ -287,8 +293,8 @@ protected: friend class SymbolRef; virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const =0; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const =0; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const = 0; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res)const=0; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const = 0; @@ -297,6 +303,7 @@ protected: uint32_t &Res) const = 0; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const = 0; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const = 0; // Same as above for SectionRef. friend class SectionRef; @@ -314,6 +321,7 @@ protected: // A section is 'virtual' if its contents aren't present in the object image. virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const = 0; virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const = 0; + 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; @@ -384,7 +392,6 @@ public: static inline bool classof(const Binary *v) { return v->isObject(); } - static inline bool classof(const ObjectFile *v) { return true; } public: static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object); @@ -401,7 +408,7 @@ inline bool SymbolRef::operator==(const SymbolRef &Other) const { return SymbolPimpl == Other.SymbolPimpl; } -inline bool SymbolRef::operator <(const SymbolRef &Other) const { +inline bool SymbolRef::operator<(const SymbolRef &Other) const { return SymbolPimpl < Other.SymbolPimpl; } @@ -441,6 +448,10 @@ inline error_code SymbolRef::getType(SymbolRef::Type &Result) const { return OwningObject->getSymbolType(SymbolPimpl, Result); } +inline error_code SymbolRef::getValue(uint64_t &Val) const { + return OwningObject->getSymbolValue(SymbolPimpl, Val); +} + inline DataRefImpl SymbolRef::getRawDataRefImpl() const { return SymbolPimpl; } @@ -456,7 +467,7 @@ inline bool SectionRef::operator==(const SectionRef &Other) const { return SectionPimpl == Other.SectionPimpl; } -inline bool SectionRef::operator <(const SectionRef &Other) const { +inline bool SectionRef::operator<(const SectionRef &Other) const { return SectionPimpl < Other.SectionPimpl; } @@ -508,6 +519,10 @@ inline error_code SectionRef::isZeroInit(bool &Result) const { return OwningObject->isSectionZeroInit(SectionPimpl, Result); } +inline error_code SectionRef::isReadOnlyData(bool &Result) const { + return OwningObject->isSectionReadOnlyData(SectionPimpl, Result); +} + inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl, Result); @@ -586,7 +601,7 @@ inline bool LibraryRef::operator==(const LibraryRef &Other) const { return LibraryPimpl == Other.LibraryPimpl; } -inline bool LibraryRef::operator <(const LibraryRef &Other) const { +inline bool LibraryRef::operator<(const LibraryRef &Other) const { return LibraryPimpl < Other.LibraryPimpl; } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h new file mode 100644 index 0000000..2c2dd03 --- /dev/null +++ b/include/llvm/Object/RelocVisitor.h @@ -0,0 +1,146 @@ +//===-- RelocVisitor.h - Visitor for object file relocations -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around all the different types of relocations +// in different file formats, such that a client can handle them in a unified +// manner by only implementing a minimal number of functions. +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_OBJECT_RELOCVISITOR +#define _LLVM_OBJECT_RELOCVISITOR + +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace object { + +struct RelocToApply { + // The computed value after applying the relevant relocations. + int64_t Value; + + // The width of the value; how many bytes to touch when applying the + // relocation. + char Width; + RelocToApply(const RelocToApply &In) : Value(In.Value), Width(In.Width) {} + RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {} + RelocToApply() : Value(0), Width(0) {} +}; + +/// @brief Base class for object file relocation visitors. +class RelocVisitor { +public: + explicit RelocVisitor(llvm::StringRef FileFormat) + : FileFormat(FileFormat), HasError(false) {} + + // TODO: Should handle multiple applied relocations via either passing in the + // previously computed value or just count paired relocations as a single + // visit. + RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0, + uint64_t Value = 0) { + if (FileFormat == "ELF64-x86-64") { + switch (RelocType) { + case llvm::ELF::R_X86_64_NONE: + return visitELF_X86_64_NONE(R); + case llvm::ELF::R_X86_64_64: + return visitELF_X86_64_64(R, Value); + case llvm::ELF::R_X86_64_PC32: + return visitELF_X86_64_PC32(R, Value, SecAddr); + case llvm::ELF::R_X86_64_32: + return visitELF_X86_64_32(R, Value); + case llvm::ELF::R_X86_64_32S: + return visitELF_X86_64_32S(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF32-i386") { + switch (RelocType) { + case llvm::ELF::R_386_NONE: + return visitELF_386_NONE(R); + case llvm::ELF::R_386_32: + return visitELF_386_32(R, Value); + case llvm::ELF::R_386_PC32: + return visitELF_386_PC32(R, Value, SecAddr); + default: + HasError = true; + return RelocToApply(); + } + } + return RelocToApply(); + } + + bool error() { return HasError; } + +private: + llvm::StringRef FileFormat; + bool HasError; + + /// Operations + + /// 386-ELF + RelocToApply visitELF_386_NONE(RelocationRef R) { + return RelocToApply(0, 0); + } + + // Ideally the Addend here will be the addend in the data for + // the relocation. It's not actually the case for Rel relocations. + RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + return RelocToApply(Value + Addend, 4); + } + + RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, + uint64_t SecAddr) { + int64_t Addend; + R.getAdditionalInfo(Addend); + uint64_t Address; + R.getAddress(Address); + return RelocToApply(Value + Addend - Address, 4); + } + + /// X86-64 ELF + RelocToApply visitELF_X86_64_NONE(RelocationRef R) { + return RelocToApply(0, 0); + } + RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + return RelocToApply(Value + Addend, 8); + } + RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, + uint64_t SecAddr) { + int64_t Addend; + R.getAdditionalInfo(Addend); + uint64_t Address; + R.getAddress(Address); + return RelocToApply(Value + Addend - Address, 4); + } + RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + int32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } +}; + +} +} +#endif diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h new file mode 100644 index 0000000..baa4b6a --- /dev/null +++ b/include/llvm/Option/Arg.h @@ -0,0 +1,132 @@ +//===--- Arg.h - Parsed Argument Classes ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the llvm::Arg class for parsed arguments. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARG_H_ +#define LLVM_SUPPORT_ARG_H_ + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/Option.h" +#include <string> + +namespace llvm { +namespace opt { +class ArgList; + +/// \brief A concrete instance of a particular driver option. +/// +/// The Arg class encodes just enough information to be able to +/// derive the argument values efficiently. In addition, Arg +/// instances have an intrusive double linked list which is used by +/// ArgList to provide efficient iteration over all instances of a +/// particular option. +class Arg { + Arg(const Arg &) LLVM_DELETED_FUNCTION; + void operator=(const Arg &) LLVM_DELETED_FUNCTION; + +private: + /// \brief The option this argument is an instance of. + const Option Opt; + + /// \brief The argument this argument was derived from (during tool chain + /// argument translation), if any. + const Arg *BaseArg; + + /// \brief How this instance of the option was spelled. + StringRef Spelling; + + /// \brief The index at which this argument appears in the containing + /// ArgList. + unsigned Index; + + /// \brief Was this argument used to effect compilation? + /// + /// This is used for generating "argument unused" diagnostics. + mutable unsigned Claimed : 1; + + /// \brief Does this argument own its values? + mutable unsigned OwnsValues : 1; + + /// \brief The argument values, as C strings. + SmallVector<const char *, 2> Values; + +public: + Arg(const Option Opt, StringRef Spelling, unsigned Index, + const Arg *BaseArg = 0); + Arg(const Option Opt, StringRef Spelling, unsigned Index, + const char *Value0, const Arg *BaseArg = 0); + Arg(const Option Opt, StringRef Spelling, unsigned Index, + const char *Value0, const char *Value1, const Arg *BaseArg = 0); + ~Arg(); + + const Option getOption() const { return Opt; } + StringRef getSpelling() const { return Spelling; } + unsigned getIndex() const { return Index; } + + /// \brief Return the base argument which generated this arg. + /// + /// This is either the argument itself or the argument it was + /// derived from during tool chain specific argument translation. + const Arg &getBaseArg() const { + return BaseArg ? *BaseArg : *this; + } + void setBaseArg(const Arg *_BaseArg) { + BaseArg = _BaseArg; + } + + bool getOwnsValues() const { return OwnsValues; } + void setOwnsValues(bool Value) const { OwnsValues = Value; } + + bool isClaimed() const { return getBaseArg().Claimed; } + + /// \brief Set the Arg claimed bit. + void claim() const { getBaseArg().Claimed = true; } + + unsigned getNumValues() const { return Values.size(); } + const char *getValue(unsigned N = 0) const { + return Values[N]; + } + + SmallVectorImpl<const char*> &getValues() { + return Values; + } + + bool containsValue(StringRef Value) const { + for (unsigned i = 0, e = getNumValues(); i != e; ++i) + if (Values[i] == Value) + return true; + return false; + } + + /// \brief Append the argument onto the given array as strings. + void render(const ArgList &Args, ArgStringList &Output) const; + + /// \brief Append the argument, render as an input, onto the given + /// array as strings. + /// + /// The distinction is that some options only render their values + /// when rendered as a input (e.g., Xlinker). + void renderAsInput(const ArgList &Args, ArgStringList &Output) const; + + void dump() const; + + /// \brief Return a formatted version of the argument and + /// its values, for debugging and diagnostics. + std::string getAsString(const ArgList &Args) const; +}; + +} // end namespace opt +} // end namespace llvm + +#endif diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h new file mode 100644 index 0000000..378b58a --- /dev/null +++ b/include/llvm/Option/ArgList.h @@ -0,0 +1,414 @@ +//===--- ArgList.h - Argument List Management -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARGLIST_H_ +#define LLVM_SUPPORT_ARGLIST_H_ + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/OptSpecifier.h" +#include "llvm/Option/Option.h" +#include <list> +#include <string> +#include <vector> + +namespace llvm { +namespace opt { +class Arg; +class ArgList; +class Option; + +/// arg_iterator - Iterates through arguments stored inside an ArgList. +class arg_iterator { + /// The current argument. + SmallVectorImpl<Arg*>::const_iterator Current; + + /// The argument list we are iterating over. + const ArgList &Args; + + /// Optional filters on the arguments which will be match. Most clients + /// should never want to iterate over arguments without filters, so we won't + /// bother to factor this into two separate iterator implementations. + // + // FIXME: Make efficient; the idea is to provide efficient iteration over + // all arguments which match a particular id and then just provide an + // iterator combinator which takes multiple iterators which can be + // efficiently compared and returns them in order. + OptSpecifier Id0, Id1, Id2; + + void SkipToNextArg(); + +public: + typedef Arg * const * value_type; + typedef Arg * const & reference; + typedef Arg * const * pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + arg_iterator(SmallVectorImpl<Arg*>::const_iterator it, + const ArgList &_Args, OptSpecifier _Id0 = 0U, + OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U) + : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) { + SkipToNextArg(); + } + + operator const Arg*() { return *Current; } + reference operator*() const { return *Current; } + pointer operator->() const { return Current; } + + arg_iterator &operator++() { + ++Current; + SkipToNextArg(); + return *this; + } + + arg_iterator operator++(int) { + arg_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(arg_iterator LHS, arg_iterator RHS) { + return LHS.Current == RHS.Current; + } + friend bool operator!=(arg_iterator LHS, arg_iterator RHS) { + return !(LHS == RHS); + } +}; + +/// ArgList - Ordered collection of driver arguments. +/// +/// The ArgList class manages a list of Arg instances as well as +/// auxiliary data and convenience methods to allow Tools to quickly +/// check for the presence of Arg instances for a particular Option +/// and to iterate over groups of arguments. +class ArgList { +private: + ArgList(const ArgList &) LLVM_DELETED_FUNCTION; + void operator=(const ArgList &) LLVM_DELETED_FUNCTION; + +public: + typedef SmallVector<Arg*, 16> arglist_type; + typedef arglist_type::iterator iterator; + typedef arglist_type::const_iterator const_iterator; + typedef arglist_type::reverse_iterator reverse_iterator; + typedef arglist_type::const_reverse_iterator const_reverse_iterator; + +private: + /// The internal list of arguments. + arglist_type Args; + +protected: + ArgList(); + +public: + virtual ~ArgList(); + + /// @name Arg Access + /// @{ + + /// append - Append \p A to the arg list. + void append(Arg *A); + + arglist_type &getArgs() { return Args; } + const arglist_type &getArgs() const { return Args; } + + unsigned size() const { return Args.size(); } + + /// @} + /// @name Arg Iteration + /// @{ + + iterator begin() { return Args.begin(); } + iterator end() { return Args.end(); } + + reverse_iterator rbegin() { return Args.rbegin(); } + reverse_iterator rend() { return Args.rend(); } + + const_iterator begin() const { return Args.begin(); } + const_iterator end() const { return Args.end(); } + + const_reverse_iterator rbegin() const { return Args.rbegin(); } + const_reverse_iterator rend() const { return Args.rend(); } + + arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, + OptSpecifier Id2 = 0U) const { + return arg_iterator(Args.begin(), *this, Id0, Id1, Id2); + } + arg_iterator filtered_end() const { + return arg_iterator(Args.end(), *this); + } + + /// @} + /// @name Arg Removal + /// @{ + + /// eraseArg - Remove any option matching \p Id. + void eraseArg(OptSpecifier Id); + + /// @} + /// @name Arg Access + /// @{ + + /// hasArg - Does the arg list contain any option matching \p Id. + /// + /// \p Claim Whether the argument should be claimed, if it exists. + bool hasArgNoClaim(OptSpecifier Id) const { + return getLastArgNoClaim(Id) != 0; + } + bool hasArg(OptSpecifier Id) const { + return getLastArg(Id) != 0; + } + bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const { + return getLastArg(Id0, Id1) != 0; + } + bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const { + return getLastArg(Id0, Id1, Id2) != 0; + } + + /// getLastArg - Return the last argument matching \p Id, or null. + /// + /// \p Claim Whether the argument should be claimed, if it exists. + Arg *getLastArgNoClaim(OptSpecifier Id) const; + Arg *getLastArg(OptSpecifier Id) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5, + OptSpecifier Id6) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5, + OptSpecifier Id6, OptSpecifier Id7) const; + + /// getArgString - Return the input argument string at \p Index. + virtual const char *getArgString(unsigned Index) const = 0; + + /// getNumInputArgStrings - Return the number of original argument strings, + /// which are guaranteed to be the first strings in the argument string + /// list. + virtual unsigned getNumInputArgStrings() const = 0; + + /// @} + /// @name Argument Lookup Utilities + /// @{ + + /// getLastArgValue - Return the value of the last argument, or a default. + StringRef getLastArgValue(OptSpecifier Id, + StringRef Default = "") const; + + /// getAllArgValues - Get the values of all instances of the given argument + /// as strings. + std::vector<std::string> getAllArgValues(OptSpecifier Id) const; + + /// @} + /// @name Translation Utilities + /// @{ + + /// hasFlag - Given an option \p Pos and its negative form \p Neg, return + /// true if the option is present, false if the negation is present, and + /// \p Default if neither option is given. If both the option and its + /// negation are present, the last one wins. + bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const; + + /// AddLastArg - Render only the last argument match \p Id0, if present. + void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; + + /// AddAllArgs - Render all arguments matching the given ids. + void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; + + /// AddAllArgValues - Render the argument values of all arguments + /// matching the given ids. + void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; + + /// AddAllArgsTranslated - Render all the arguments matching the + /// given ids, but forced to separate args and using the provided + /// name instead of the first option value. + /// + /// \param Joined - If true, render the argument as joined with + /// the option specifier. + void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, + const char *Translation, + bool Joined = false) const; + + /// ClaimAllArgs - Claim all arguments which match the given + /// option id. + void ClaimAllArgs(OptSpecifier Id0) const; + + /// ClaimAllArgs - Claim all arguments. + /// + void ClaimAllArgs() const; + + /// @} + /// @name Arg Synthesis + /// @{ + + /// MakeArgString - Construct a constant string pointer whose + /// lifetime will match that of the ArgList. + virtual const char *MakeArgString(StringRef Str) const = 0; + const char *MakeArgString(const char *Str) const { + return MakeArgString(StringRef(Str)); + } + const char *MakeArgString(std::string Str) const { + return MakeArgString(StringRef(Str)); + } + const char *MakeArgString(const Twine &Str) const; + + /// \brief Create an arg string for (\p LHS + \p RHS), reusing the + /// string at \p Index if possible. + const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS, + StringRef RHS) const; + + /// @} +}; + +class InputArgList : public ArgList { +private: + /// List of argument strings used by the contained Args. + /// + /// This is mutable since we treat the ArgList as being the list + /// of Args, and allow routines to add new strings (to have a + /// convenient place to store the memory) via MakeIndex. + mutable ArgStringList ArgStrings; + + /// Strings for synthesized arguments. + /// + /// This is mutable since we treat the ArgList as being the list + /// of Args, and allow routines to add new strings (to have a + /// convenient place to store the memory) via MakeIndex. + mutable std::list<std::string> SynthesizedStrings; + + /// The number of original input argument strings. + unsigned NumInputArgStrings; + +public: + InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); + ~InputArgList(); + + virtual const char *getArgString(unsigned Index) const { + return ArgStrings[Index]; + } + + virtual unsigned getNumInputArgStrings() const { + return NumInputArgStrings; + } + + /// @name Arg Synthesis + /// @{ + +public: + /// MakeIndex - Get an index for the given string(s). + unsigned MakeIndex(StringRef String0) const; + unsigned MakeIndex(StringRef String0, StringRef String1) const; + + virtual const char *MakeArgString(StringRef Str) const; + + /// @} +}; + +/// DerivedArgList - An ordered collection of driver arguments, +/// whose storage may be in another argument list. +class DerivedArgList : public ArgList { + const InputArgList &BaseArgs; + + /// The list of arguments we synthesized. + mutable arglist_type SynthesizedArgs; + +public: + /// Construct a new derived arg list from \p BaseArgs. + DerivedArgList(const InputArgList &BaseArgs); + ~DerivedArgList(); + + virtual const char *getArgString(unsigned Index) const { + return BaseArgs.getArgString(Index); + } + + virtual unsigned getNumInputArgStrings() const { + return BaseArgs.getNumInputArgStrings(); + } + + const InputArgList &getBaseArgs() const { + return BaseArgs; + } + + /// @name Arg Synthesis + /// @{ + + /// AddSynthesizedArg - Add a argument to the list of synthesized arguments + /// (to be freed). + void AddSynthesizedArg(Arg *A) { + SynthesizedArgs.push_back(A); + } + + virtual const char *MakeArgString(StringRef Str) const; + + /// AddFlagArg - Construct a new FlagArg for the given option \p Id and + /// append it to the argument list. + void AddFlagArg(const Arg *BaseArg, const Option Opt) { + append(MakeFlagArg(BaseArg, Opt)); + } + + /// AddPositionalArg - Construct a new Positional arg for the given option + /// \p Id, with the provided \p Value and append it to the argument + /// list. + void AddPositionalArg(const Arg *BaseArg, const Option Opt, + StringRef Value) { + append(MakePositionalArg(BaseArg, Opt, Value)); + } + + + /// AddSeparateArg - Construct a new Positional arg for the given option + /// \p Id, with the provided \p Value and append it to the argument + /// list. + void AddSeparateArg(const Arg *BaseArg, const Option Opt, + StringRef Value) { + append(MakeSeparateArg(BaseArg, Opt, Value)); + } + + + /// AddJoinedArg - Construct a new Positional arg for the given option + /// \p Id, with the provided \p Value and append it to the argument list. + void AddJoinedArg(const Arg *BaseArg, const Option Opt, + StringRef Value) { + append(MakeJoinedArg(BaseArg, Opt, Value)); + } + + + /// MakeFlagArg - Construct a new FlagArg for the given option \p Id. + Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const; + + /// MakePositionalArg - Construct a new Positional arg for the + /// given option \p Id, with the provided \p Value. + Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt, + StringRef Value) const; + + /// MakeSeparateArg - Construct a new Positional arg for the + /// given option \p Id, with the provided \p Value. + Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt, + StringRef Value) const; + + /// MakeJoinedArg - Construct a new Positional arg for the + /// given option \p Id, with the provided \p Value. + Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt, + StringRef Value) const; + + /// @} +}; + +} // end namespace opt +} // end namespace llvm + +#endif diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td new file mode 100644 index 0000000..e781fa0 --- /dev/null +++ b/include/llvm/Option/OptParser.td @@ -0,0 +1,127 @@ +//===--- OptParser.td - Common Option Parsing Interfaces ------------------===// +// +// 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 common interfaces used by the option parsing TableGen +// backend. +// +//===----------------------------------------------------------------------===// + +// Define the kinds of options. + +class OptionKind<string name, int predecence = 0, bit sentinel = 0> { + string Name = name; + // The kind precedence, kinds with lower precedence are matched first. + int Precedence = predecence; + // Indicate a sentinel option. + bit Sentinel = sentinel; +} + +// An option group. +def KIND_GROUP : OptionKind<"Group">; +// The input option kind. +def KIND_INPUT : OptionKind<"Input", 1, 1>; +// The unknown option kind. +def KIND_UNKNOWN : OptionKind<"Unknown", 2, 1>; +// A flag with no values. +def KIND_FLAG : OptionKind<"Flag">; +// An option which prefixes its (single) value. +def KIND_JOINED : OptionKind<"Joined", 1>; +// An option which is followed by its value. +def KIND_SEPARATE : OptionKind<"Separate">; +// An option followed by its values, which are separated by commas. +def KIND_COMMAJOINED : OptionKind<"CommaJoined">; +// An option which is which takes multiple (separate) arguments. +def KIND_MULTIARG : OptionKind<"MultiArg">; +// An option which is either joined to its (non-empty) value, or followed by its +// value. +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">; + +// Define the option flags. + +class OptionFlag {} + +// HelpHidden - The option should not be displayed in --help, even if it has +// help text. Clients *can* use this in conjunction with the OptTable::PrintHelp +// arguments to implement hidden help groups. +def HelpHidden : OptionFlag; + +// RenderAsInput - The option should not render the name when rendered as an +// input (i.e., the option is rendered as values). +def RenderAsInput : OptionFlag; + +// RenderJoined - The option should be rendered joined, even if separate (only +// sensible on single value separate options). +def RenderJoined : OptionFlag; + +// RenderSeparate - The option should be rendered separately, even if joined +// (only sensible on joined options). +def RenderSeparate : OptionFlag; + +// Define the option group class. + +class OptionGroup<string name> { + string EnumName = ?; // Uses the def name if undefined. + string Name = name; + string HelpText = ?; + OptionGroup Group = ?; +} + +// Define the option class. + +class Option<list<string> prefixes, string name, OptionKind kind> { + string EnumName = ?; // Uses the def name if undefined. + list<string> Prefixes = prefixes; + string Name = name; + OptionKind Kind = kind; + // Used by MultiArg option kind. + int NumArgs = 0; + string HelpText = ?; + string MetaVarName = ?; + list<OptionFlag> Flags = []; + OptionGroup Group = ?; + Option Alias = ?; +} + +// Helpers for defining options. + +class Flag<list<string> prefixes, string name> + : Option<prefixes, name, KIND_FLAG>; +class Joined<list<string> prefixes, string name> + : Option<prefixes, name, KIND_JOINED>; +class Separate<list<string> prefixes, string name> + : Option<prefixes, name, KIND_SEPARATE>; +class CommaJoined<list<string> prefixes, string name> + : Option<prefixes, name, KIND_COMMAJOINED>; +class MultiArg<list<string> prefixes, string name, int numargs> + : Option<prefixes, name, KIND_MULTIARG> { + int NumArgs = numargs; +} +class JoinedOrSeparate<list<string> prefixes, string name> + : Option<prefixes, name, KIND_JOINED_OR_SEPARATE>; +class JoinedAndSeparate<list<string> prefixes, string name> + : Option<prefixes, name, KIND_JOINED_AND_SEPARATE>; + +// Mix-ins for adding optional attributes. + +class Alias<Option alias> { Option Alias = alias; } +class EnumName<string name> { string EnumName = name; } +class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; } +class Group<OptionGroup group> { OptionGroup Group = group; } +class HelpText<string text> { string HelpText = text; } +class MetaVarName<string name> { string MetaVarName = name; } + +// Predefined options. + +// FIXME: Have generator validate that these appear in correct position (and +// aren't duplicated). +def INPUT : Option<[], "<input>", KIND_INPUT>; +def UNKNOWN : Option<[], "<unknown>", KIND_UNKNOWN>; diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h new file mode 100644 index 0000000..3bc9bb2 --- /dev/null +++ b/include/llvm/Option/OptSpecifier.h @@ -0,0 +1,39 @@ +//===--- OptSpecifier.h - Option Specifiers ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_OPTSPECIFIER_H +#define LLVM_SUPPORT_OPTSPECIFIER_H + +namespace llvm { +namespace opt { + class Option; + + /// OptSpecifier - Wrapper class for abstracting references to option IDs. + class OptSpecifier { + unsigned ID; + + private: + explicit OptSpecifier(bool); // DO NOT IMPLEMENT + + public: + OptSpecifier() : ID(0) {} + /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {} + /*implicit*/ OptSpecifier(const Option *Opt); + + bool isValid() const { return ID != 0; } + + unsigned getID() const { return ID; } + + bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); } + bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); } + }; +} +} + +#endif diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h new file mode 100644 index 0000000..930549f --- /dev/null +++ b/include/llvm/Option/OptTable.h @@ -0,0 +1,161 @@ +//===--- OptTable.h - Option Table ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_OPTTABLE_H +#define LLVM_SUPPORT_OPTTABLE_H + +#include "llvm/ADT/StringSet.h" +#include "llvm/Option/OptSpecifier.h" + +namespace llvm { +class raw_ostream; +namespace opt { +class Arg; +class ArgList; +class InputArgList; +class Option; + +/// \brief Provide access to the Option info table. +/// +/// The OptTable class provides a layer of indirection which allows Option +/// instance to be created lazily. In the common case, only a few options will +/// be needed at runtime; the OptTable class maintains enough information to +/// parse command lines without instantiating Options, while letting other +/// parts of the driver still use Option instances where convenient. +class OptTable { +public: + /// \brief Entry for a single option instance in the option data table. + struct Info { + /// A null terminated array of prefix strings to apply to name while + /// matching. + const char *const *Prefixes; + const char *Name; + const char *HelpText; + const char *MetaVar; + unsigned ID; + unsigned char Kind; + unsigned char Param; + unsigned short Flags; + unsigned short GroupID; + unsigned short AliasID; + }; + +private: + /// \brief The static option information table. + const Info *OptionInfos; + unsigned NumOptionInfos; + + unsigned TheInputOptionID; + unsigned TheUnknownOptionID; + + /// The index of the first option which can be parsed (i.e., is not a + /// special option like 'input' or 'unknown', and is not an option group). + unsigned FirstSearchableIndex; + + /// The union of all option prefixes. If an argument does not begin with + /// one of these, it is an input. + StringSet<> PrefixesUnion; + std::string PrefixChars; + +private: + const Info &getInfo(OptSpecifier Opt) const { + unsigned id = Opt.getID(); + assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID."); + return OptionInfos[id - 1]; + } + +protected: + OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos); +public: + ~OptTable(); + + /// \brief Return the total number of option classes. + unsigned getNumOptions() const { return NumOptionInfos; } + + /// \brief Get the given Opt's Option instance, lazily creating it + /// if necessary. + /// + /// \return The option, or null for the INVALID option id. + const Option getOption(OptSpecifier Opt) const; + + /// \brief Lookup the name of the given option. + const char *getOptionName(OptSpecifier id) const { + return getInfo(id).Name; + } + + /// \brief Get the kind of the given option. + unsigned getOptionKind(OptSpecifier id) const { + return getInfo(id).Kind; + } + + /// \brief Get the group id for the given option. + unsigned getOptionGroupID(OptSpecifier id) const { + return getInfo(id).GroupID; + } + + /// \brief Should the help for the given option be hidden by default. + bool isOptionHelpHidden(OptSpecifier id) const; + + /// \brief Get the help text to use to describe this option. + const char *getOptionHelpText(OptSpecifier id) const { + return getInfo(id).HelpText; + } + + /// \brief Get the meta-variable name to use when describing + /// this options values in the help text. + const char *getOptionMetaVar(OptSpecifier id) const { + return getInfo(id).MetaVar; + } + + /// \brief Parse a single argument; returning the new argument and + /// updating Index. + /// + /// \param [in,out] Index - The current parsing position in the argument + /// string list; on return this will be the index of the next argument + /// string to parse. + /// + /// \return The parsed argument, or 0 if the argument is missing values + /// (in which case Index still points at the conceptual next argument string + /// to parse). + Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const; + + /// \brief Parse an list of arguments into an InputArgList. + /// + /// The resulting InputArgList will reference the strings in [\p ArgBegin, + /// \p ArgEnd), and their lifetime should extend past that of the returned + /// InputArgList. + /// + /// The only error that can occur in this routine is if an argument is + /// missing values; in this case \p MissingArgCount will be non-zero. + /// + /// \param ArgBegin - The beginning of the argument vector. + /// \param ArgEnd - The end of the argument vector. + /// \param MissingArgIndex - On error, the index of the option which could + /// not be parsed. + /// \param MissingArgCount - On error, the number of missing options. + /// \return An InputArgList; on error this will contain all the options + /// which could be parsed. + InputArgList *ParseArgs(const char* const *ArgBegin, + const char* const *ArgEnd, + unsigned &MissingArgIndex, + unsigned &MissingArgCount) const; + + /// \brief Render the help text for an option table. + /// + /// \param OS - The stream to write the help text to. + /// \param Name - The name to use in the usage line. + /// \param Title - The title to use in the usage line. + /// \param ShowHidden - Whether help-hidden arguments should be shown. + void PrintHelp(raw_ostream &OS, const char *Name, + const char *Title, bool ShowHidden = false) const; +}; +} // end namespace opt +} // end namespace llvm + +#endif diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h new file mode 100644 index 0000000..ee5eec4 --- /dev/null +++ b/include/llvm/Option/Option.h @@ -0,0 +1,193 @@ +//===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_OPTION_H_ +#define LLVM_SUPPORT_OPTION_H_ + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/OptTable.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { +namespace opt { +class Arg; +class ArgList; +/// ArgStringList - Type used for constructing argv lists for subprocesses. +typedef SmallVector<const char*, 16> ArgStringList; + +/// Base flags for all options. Custom flags may be added after. +enum DriverFlag { + HelpHidden = (1 << 0), + RenderAsInput = (1 << 1), + RenderJoined = (1 << 2), + RenderSeparate = (1 << 3) +}; + +/// Option - Abstract representation for a single form of driver +/// argument. +/// +/// An Option class represents a form of option that the driver +/// takes, for example how many arguments the option has and how +/// they can be provided. Individual option instances store +/// additional information about what group the option is a member +/// of (if any), if the option is an alias, and a number of +/// flags. At runtime the driver parses the command line into +/// concrete Arg instances, each of which corresponds to a +/// particular Option instance. +class Option { +public: + enum OptionClass { + GroupClass = 0, + InputClass, + UnknownClass, + FlagClass, + JoinedClass, + SeparateClass, + CommaJoinedClass, + MultiArgClass, + JoinedOrSeparateClass, + JoinedAndSeparateClass + }; + + enum RenderStyleKind { + RenderCommaJoinedStyle, + RenderJoinedStyle, + RenderSeparateStyle, + RenderValuesStyle + }; + +protected: + const OptTable::Info *Info; + const OptTable *Owner; + +public: + Option(const OptTable::Info *Info, const OptTable *Owner); + ~Option(); + + bool isValid() const { + return Info != 0; + } + + unsigned getID() const { + assert(Info && "Must have a valid info!"); + return Info->ID; + } + + OptionClass getKind() const { + assert(Info && "Must have a valid info!"); + return OptionClass(Info->Kind); + } + + /// \brief Get the name of this option without any prefix. + StringRef getName() const { + assert(Info && "Must have a valid info!"); + return Info->Name; + } + + const Option getGroup() const { + assert(Info && "Must have a valid info!"); + assert(Owner && "Must have a valid owner!"); + return Owner->getOption(Info->GroupID); + } + + const Option getAlias() const { + assert(Info && "Must have a valid info!"); + assert(Owner && "Must have a valid owner!"); + return Owner->getOption(Info->AliasID); + } + + /// \brief Get the default prefix for this option. + StringRef getPrefix() const { + const char *Prefix = *Info->Prefixes; + return Prefix ? Prefix : StringRef(); + } + + /// \brief Get the name of this option with the default prefix. + std::string getPrefixedName() const { + std::string Ret = getPrefix(); + Ret += getName(); + return Ret; + } + + unsigned getNumArgs() const { return Info->Param; } + + bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;} + + RenderStyleKind getRenderStyle() const { + if (Info->Flags & RenderJoined) + return RenderJoinedStyle; + if (Info->Flags & RenderSeparate) + return RenderSeparateStyle; + switch (getKind()) { + case GroupClass: + case InputClass: + case UnknownClass: + return RenderValuesStyle; + case JoinedClass: + case JoinedAndSeparateClass: + return RenderJoinedStyle; + case CommaJoinedClass: + return RenderCommaJoinedStyle; + case FlagClass: + case SeparateClass: + case MultiArgClass: + case JoinedOrSeparateClass: + return RenderSeparateStyle; + } + llvm_unreachable("Unexpected kind!"); + } + + /// Test if this option has the flag \a Val. + bool hasFlag(unsigned Val) const { + return Info->Flags & Val; + } + + /// getUnaliasedOption - Return the final option this option + /// aliases (itself, if the option has no alias). + const Option getUnaliasedOption() const { + const Option Alias = getAlias(); + if (Alias.isValid()) return Alias.getUnaliasedOption(); + return *this; + } + + /// getRenderName - Return the name to use when rendering this + /// option. + StringRef getRenderName() const { + return getUnaliasedOption().getName(); + } + + /// matches - Predicate for whether this option is part of the + /// given option (which may be a group). + /// + /// Note that matches against options which are an alias should never be + /// done -- aliases do not participate in matching and so such a query will + /// always be false. + bool matches(OptSpecifier ID) const; + + /// accept - Potentially accept the current argument, returning a + /// new Arg instance, or 0 if the option does not accept this + /// argument (or the argument is missing values). + /// + /// If the option accepts the current argument, accept() sets + /// Index to the position where argument parsing should resume + /// (even if the argument is missing values). + /// + /// \parm ArgSize The number of bytes taken up by the matched Option prefix + /// and name. This is used to determine where joined values + /// start. + Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const; + + void dump() const; +}; + +} // end namespace opt +} // end namespace llvm + +#endif diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index 888537d..35ec022 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -29,6 +29,7 @@ #ifndef LLVM_PASS_H #define LLVM_PASS_H +#include "llvm/Support/Compiler.h" #include <string> namespace llvm { @@ -82,8 +83,8 @@ class Pass { AnalysisResolver *Resolver; // Used to resolve analysis const void *PassID; PassKind Kind; - void operator=(const Pass&); // DO NOT IMPLEMENT - Pass(const Pass &); // DO NOT IMPLEMENT + void operator=(const Pass&) LLVM_DELETED_FUNCTION; + Pass(const Pass &) LLVM_DELETED_FUNCTION; public: explicit Pass(PassKind K, char &pid) : Resolver(0), PassID(&pid), Kind(K) { } @@ -103,6 +104,16 @@ public: return PassID; } + /// doInitialization - Virtual method overridden by subclasses to do + /// any necessary initialization before any pass is run. + /// + virtual bool doInitialization(Module &) { return false; } + + /// doFinalization - Virtual method overriden by subclasses to do any + /// necessary clean up after all passes have run. + /// + virtual bool doFinalization(Module &) { return false; } + /// print - Print out the internal state of the pass. This is called by /// Analyze to print out the contents of an analysis. Otherwise it is not /// necessary to implement this method. Beware that the module pointer MAY be @@ -286,21 +297,11 @@ public: /// createPrinterPass - Get a function printer pass. Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; - /// doInitialization - Virtual method overridden by subclasses to do - /// any necessary per-module initialization. - /// - virtual bool doInitialization(Module &); - /// runOnFunction - Virtual method overriden by subclasses to do the /// per-function processing of the pass. /// virtual bool runOnFunction(Function &F) = 0; - /// doFinalization - Virtual method overriden by subclasses to do any post - /// processing needed after all passes have run. - /// - virtual bool doFinalization(Module &); - virtual void assignPassManager(PMStack &PMS, PassManagerType T); @@ -327,10 +328,8 @@ public: /// createPrinterPass - Get a basic block printer pass. Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; - /// doInitialization - Virtual method overridden by subclasses to do - /// any necessary per-module initialization. - /// - virtual bool doInitialization(Module &); + using llvm::Pass::doInitialization; + using llvm::Pass::doFinalization; /// doInitialization - Virtual method overridden by BasicBlockPass subclasses /// to do any necessary per-function initialization. @@ -347,11 +346,6 @@ public: /// virtual bool doFinalization(Function &); - /// doFinalization - Virtual method overriden by subclasses to do any post - /// processing needed after all passes have run. - /// - virtual bool doFinalization(Module &); - virtual void assignPassManager(PMStack &PMS, PassManagerType T); diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index 5c6a2d7..1cc5741 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -19,9 +19,9 @@ #ifndef LLVM_PASS_ANALYSIS_SUPPORT_H #define LLVM_PASS_ANALYSIS_SUPPORT_H -#include "llvm/Pass.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Pass.h" #include <vector> namespace llvm { @@ -120,7 +120,7 @@ public: class PMDataManager; class AnalysisResolver { private: - AnalysisResolver(); // DO NOT IMPLEMENT + AnalysisResolver() LLVM_DELETED_FUNCTION; public: explicit AnalysisResolver(PMDataManager &P) : PM(P) { } diff --git a/include/llvm/PassManagers.h b/include/llvm/PassManagers.h index 0af5853..fac7928 100644 --- a/include/llvm/PassManagers.h +++ b/include/llvm/PassManagers.h @@ -14,13 +14,13 @@ #ifndef LLVM_PASSMANAGERS_H #define LLVM_PASSMANAGERS_H -#include "llvm/Pass.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/DenseMap.h" -#include <vector> +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Pass.h" #include <map> +#include <vector> //===----------------------------------------------------------------------===// // Overview: @@ -168,7 +168,7 @@ class PMTopLevelManager { protected: explicit PMTopLevelManager(PMDataManager *PMDM); - virtual unsigned getNumContainedManagers() const { + unsigned getNumContainedManagers() const { return (unsigned)PassManagers.size(); } @@ -343,7 +343,7 @@ public: void dumpRequiredSet(const Pass *P) const; void dumpPreservedSet(const Pass *P) const; - virtual unsigned getNumContainedPasses() const { + unsigned getNumContainedPasses() const { return (unsigned)PassVector.size(); } @@ -420,10 +420,20 @@ public: /// cleanup - After running all passes, clean up pass manager cache. void cleanup(); + /// doInitialization - Overrides ModulePass doInitialization for global + /// initialization tasks + /// + using ModulePass::doInitialization; + /// doInitialization - Run all of the initializers for the function passes. /// bool doInitialization(Module &M); + /// doFinalization - Overrides ModulePass doFinalization for global + /// finalization tasks + /// + using ModulePass::doFinalization; + /// doFinalization - Run all of the finalizers for the function passes. /// bool doFinalization(Module &M); diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index c50c2cc..3633f47 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -22,8 +22,8 @@ #define LLVM_PASS_SUPPORT_H #include "Pass.h" -#include "llvm/PassRegistry.h" #include "llvm/InitializePasses.h" +#include "llvm/PassRegistry.h" #include "llvm/Support/Atomic.h" #include "llvm/Support/Valgrind.h" #include <vector> @@ -126,8 +126,8 @@ public: } private: - void operator=(const PassInfo &); // do not implement - PassInfo(const PassInfo &); // do not implement + void operator=(const PassInfo &) LLVM_DELETED_FUNCTION; + PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION; }; #define CALL_ONCE_INITIALIZATION(function) \ @@ -305,7 +305,7 @@ struct RegisterAnalysisGroup : public RegisterAGBase { /// clients that are interested in which passes get registered and unregistered /// at runtime (which can be because of the RegisterPass constructors being run /// as the program starts up, or may be because a shared object just got -/// loaded). Deriving from the PassRegistationListener class automatically +/// loaded). Deriving from the PassRegistrationListener class automatically /// registers your object to receive callbacks indicating when passes are loaded /// and removed. /// diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 8c389af..0894316 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -19,7 +19,6 @@ #include <cstddef> namespace llvm { - template <typename T> struct AlignmentCalcImpl { char x; @@ -49,7 +48,6 @@ struct AlignOf { enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; - }; /// alignOf - A templated function that returns the minimum alignment of @@ -59,121 +57,145 @@ struct AlignOf { template <typename T> inline unsigned alignOf() { return AlignOf<T>::Alignment; } - +/// \struct AlignedCharArray /// \brief Helper for building an aligned character array type. /// /// This template is used to explicitly build up a collection of aligned -/// character types. We have to build these up using a macro and explicit +/// character array types. We have to build these up using a macro and explicit /// specialization to cope with old versions of MSVC and GCC where only an /// integer literal can be used to specify an alignment constraint. Once built /// up here, we can then begin to indirect between these using normal C++ /// template parameters. -template <size_t Alignment> struct AlignedCharArrayImpl {}; -template <> struct AlignedCharArrayImpl<0> { - typedef char type; -}; // MSVC requires special handling here. #ifndef _MSC_VER #if __has_feature(cxx_alignas) +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray { + alignas(Alignment) char buffer[Size]; +}; + +#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES) +/// \brief Create a type with an aligned char buffer. +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray; + #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ - template <> struct AlignedCharArrayImpl<x> { \ - typedef char alignas(x) type; \ - } -#elif defined(__clang__) || defined(__GNUC__) -#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ - template <> struct AlignedCharArrayImpl<x> { \ - typedef char type __attribute__((aligned(x))); \ - } -#else -# error No supported align as directive. -#endif + template<std::size_t Size> \ + struct AlignedCharArray<x, Size> { \ + __attribute__((aligned(x))) char buffer[Size]; \ + }; -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT +#else +# error No supported align as directive. +#endif + #else // _MSC_VER +/// \brief Create a type with an aligned char buffer. +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray; + // We provide special variations of this template for the most common // alignments because __declspec(align(...)) doesn't actually work when it is // a member of a by-value function argument in MSVC, even if the alignment -// request is something reasonably like 8-byte or 16-byte. -template <> struct AlignedCharArrayImpl<1> { typedef char type; }; -template <> struct AlignedCharArrayImpl<2> { typedef short type; }; -template <> struct AlignedCharArrayImpl<4> { typedef int type; }; -template <> struct AlignedCharArrayImpl<8> { typedef double type; }; +// request is something reasonably like 8-byte or 16-byte. Note that we can't +// even include the declspec with the union that forces the alignment because +// MSVC warns on the existence of the declspec despite the union member forcing +// proper alignment. + +template<std::size_t Size> +struct AlignedCharArray<1, Size> { + union { + char aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<2, Size> { + union { + short aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<4, Size> { + union { + int aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<8, Size> { + union { + double aligned; + char buffer[Size]; + }; +}; + + +// The rest of these are provided with a __declspec(align(...)) and we simply +// can't pass them by-value as function arguments on MSVC. #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ - template <> struct AlignedCharArrayImpl<x> { \ - typedef __declspec(align(x)) char type; \ - } -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); -// Any larger and MSVC complains. + template<std::size_t Size> \ + struct AlignedCharArray<x, Size> { \ + __declspec(align(x)) char buffer[Size]; \ + }; + +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) + #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT #endif // _MSC_VER +namespace detail { +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char> +class AlignerImpl { + T1 t1; T2 t2; T3 t3; T4 t4; + + AlignerImpl(); // Never defined or instantiated. +}; + +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char> +union SizerImpl { + char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)]; +}; +} // end namespace detail + /// \brief This union template exposes a suitably aligned and sized character /// array member which can hold elements of any of up to four types. /// /// These types may be arrays, structs, or any other types. The goal is to -/// produce a union type containing a character array which, when used, forms -/// storage suitable to placement new any of these types over. Support for more -/// than four types can be added at the cost of more boiler plate. +/// expose a char array buffer member which can be used as suitable storage for +/// a placement new of any of these types. Support for more than four types can +/// be added at the cost of more boiler plate. template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char> -union AlignedCharArrayUnion { -private: - class AlignerImpl { - T1 t1; T2 t2; T3 t3; T4 t4; - - AlignerImpl(); // Never defined or instantiated. - }; - union SizerImpl { - char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)]; - }; - -public: - /// \brief The character array buffer for use by clients. - /// - /// No other member of this union should be referenced. The exist purely to - /// constrain the layout of this character array. - char buffer[sizeof(SizerImpl)]; - - // Sadly, Clang and GCC both fail to align a character array properly even - // with an explicit alignment attribute. To work around this, we union - // the character array that will actually be used with a struct that contains - // a single aligned character member. Tests seem to indicate that both Clang - // and GCC will properly register the alignment of a struct containing an - // aligned member, and this alignment should carry over to the character - // array in the union. - struct { - typename llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment>::type - nonce_inner_member; - } nonce_member; +struct AlignedCharArrayUnion : + llvm::AlignedCharArray<AlignOf<detail::AlignerImpl<T1, T2, T3, T4> > + ::Alignment, + sizeof(detail::SizerImpl<T1, T2, T3, T4>)> { }; - } // end namespace llvm #endif diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index a2ad24f..3243fd9 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -15,12 +15,12 @@ #define LLVM_SUPPORT_ALLOCATOR_H #include "llvm/Support/AlignOf.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" #include <algorithm> #include <cassert> -#include <cstdlib> #include <cstddef> +#include <cstdlib> namespace llvm { template <typename T> struct ReferenceAdder { typedef T& result; }; @@ -79,8 +79,8 @@ class MallocSlabAllocator : public SlabAllocator { public: MallocSlabAllocator() : Allocator() { } virtual ~MallocSlabAllocator(); - virtual MemSlab *Allocate(size_t Size); - virtual void Deallocate(MemSlab *Slab); + virtual MemSlab *Allocate(size_t Size) LLVM_OVERRIDE; + virtual void Deallocate(MemSlab *Slab) LLVM_OVERRIDE; }; /// BumpPtrAllocator - This allocator is useful for containers that need @@ -88,8 +88,8 @@ public: /// allocating memory, and never deletes it until the entire block is dead. This /// makes allocation speedy, but must only be used when the trade-off is ok. class BumpPtrAllocator { - BumpPtrAllocator(const BumpPtrAllocator &); // do not implement - void operator=(const BumpPtrAllocator &); // do not implement + BumpPtrAllocator(const BumpPtrAllocator &) LLVM_DELETED_FUNCTION; + void operator=(const BumpPtrAllocator &) LLVM_DELETED_FUNCTION; /// SlabSize - Allocate data into slabs of this size unless we get an /// allocation above SizeThreshold. diff --git a/include/llvm/Support/ArrayRecycler.h b/include/llvm/Support/ArrayRecycler.h new file mode 100644 index 0000000..0fbe79c --- /dev/null +++ b/include/llvm/Support/ArrayRecycler.h @@ -0,0 +1,143 @@ +//==- llvm/Support/ArrayRecycler.h - Recycling of Arrays ---------*- 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 ArrayRecycler class template which can recycle small +// arrays allocated from one of the allocators in Allocator.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARRAY_RECYCLER_H +#define LLVM_SUPPORT_ARRAY_RECYCLER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MathExtras.h" + +namespace llvm { + +class BumpPtrAllocator; + +/// Recycle small arrays allocated from a BumpPtrAllocator. +/// +/// Arrays are allocated in a small number of fixed sizes. For each supported +/// array size, the ArrayRecycler keeps a free list of available arrays. +/// +template<class T, size_t Align = AlignOf<T>::Alignment> +class ArrayRecycler { + // The free list for a given array size is a simple singly linked list. + // We can't use iplist or Recycler here since those classes can't be copied. + struct FreeList { + FreeList *Next; + }; + + // Keep a free list for each array size. + SmallVector<FreeList*, 8> Bucket; + + // Remove an entry from the free list in Bucket[Idx] and return it. + // Return NULL if no entries are available. + T *pop(unsigned Idx) { + if (Idx >= Bucket.size()) + return 0; + FreeList *Entry = Bucket[Idx]; + if (!Entry) + return 0; + Bucket[Idx] = Entry->Next; + return reinterpret_cast<T*>(Entry); + } + + // Add an entry to the free list at Bucket[Idx]. + void push(unsigned Idx, T *Ptr) { + assert(Ptr && "Cannot recycle NULL pointer"); + assert(sizeof(T) >= sizeof(FreeList) && "Objects are too small"); + assert(Align >= AlignOf<FreeList>::Alignment && "Object underaligned"); + FreeList *Entry = reinterpret_cast<FreeList*>(Ptr); + if (Idx >= Bucket.size()) + Bucket.resize(size_t(Idx) + 1); + Entry->Next = Bucket[Idx]; + Bucket[Idx] = Entry; + } + +public: + /// The size of an allocated array is represented by a Capacity instance. + /// + /// This class is much smaller than a size_t, and it provides methods to work + /// with the set of legal array capacities. + class Capacity { + uint8_t Index; + explicit Capacity(uint8_t idx) : Index(idx) {} + + public: + Capacity() : Index(0) {} + + /// Get the capacity of an array that can hold at least N elements. + static Capacity get(size_t N) { + return Capacity(N ? Log2_64_Ceil(N) : 0); + } + + /// Get the number of elements in an array with this capacity. + size_t getSize() const { return size_t(1u) << Index; } + + /// Get the bucket number for this capacity. + unsigned getBucket() const { return Index; } + + /// Get the next larger capacity. Large capacities grow exponentially, so + /// this function can be used to reallocate incrementally growing vectors + /// in amortized linear time. + Capacity getNext() const { return Capacity(Index + 1); } + }; + + ~ArrayRecycler() { + // The client should always call clear() so recycled arrays can be returned + // to the allocator. + assert(Bucket.empty() && "Non-empty ArrayRecycler deleted!"); + } + + /// Release all the tracked allocations to the allocator. The recycler must + /// be free of any tracked allocations before being deleted. + template<class AllocatorType> + void clear(AllocatorType &Allocator) { + for (; !Bucket.empty(); Bucket.pop_back()) + while (T *Ptr = pop(Bucket.size() - 1)) + Allocator.Deallocate(Ptr); + } + + /// Special case for BumpPtrAllocator which has an empty Deallocate() + /// function. + /// + /// There is no need to traverse the free lists, pulling all the objects into + /// cache. + void clear(BumpPtrAllocator&) { + Bucket.clear(); + } + + /// Allocate an array of at least the requested capacity. + /// + /// Return an existing recycled array, or allocate one from Allocator if + /// none are available for recycling. + /// + template<class AllocatorType> + T *allocate(Capacity Cap, AllocatorType &Allocator) { + // Try to recycle an existing array. + if (T *Ptr = pop(Cap.getBucket())) + return Ptr; + // Nope, get more memory. + return static_cast<T*>(Allocator.Allocate(sizeof(T)*Cap.getSize(), Align)); + } + + /// Deallocate an array with the specified Capacity. + /// + /// Cap must be the same capacity that was given to allocate(). + /// + void deallocate(Capacity Cap, T *Ptr) { + push(Cap.getBucket(), Ptr); + } +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index f5dc8ea..a9fb65c 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -16,8 +16,8 @@ #define LLVM_SUPPORT_CFG_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/Function.h" -#include "llvm/InstrTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" namespace llvm { diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index 8905e1e..3ce0fef 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -26,11 +26,11 @@ #ifndef LLVM_SUPPORT_CALLSITE_H #define LLVM_SUPPORT_CALLSITE_H -#include "llvm/Attributes.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/BasicBlock.h" -#include "llvm/CallingConv.h" -#include "llvm/Instructions.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/Instructions.h" namespace llvm { @@ -177,21 +177,21 @@ public: /// getAttributes/setAttributes - get or set the parameter attributes of /// the call. - const AttrListPtr &getAttributes() const { + const AttributeSet &getAttributes() const { CALLSITE_DELEGATE_GETTER(getAttributes()); } - void setAttributes(const AttrListPtr &PAL) { + void setAttributes(const AttributeSet &PAL) { CALLSITE_DELEGATE_SETTER(setAttributes(PAL)); } /// \brief Return true if this function has the given attribute. - bool hasFnAttr(Attributes N) const { - CALLSITE_DELEGATE_GETTER(hasFnAttr(N)); + bool hasFnAttr(Attribute::AttrKind A) const { + CALLSITE_DELEGATE_GETTER(hasFnAttr(A)); } - /// paramHasAttr - whether the call or the callee has the given attribute. - bool paramHasAttr(uint16_t i, Attributes attr) const { - CALLSITE_DELEGATE_GETTER(paramHasAttr(i, attr)); + /// \brief Return true if the call or the callee has the given attribute. + bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { + CALLSITE_DELEGATE_GETTER(paramHasAttr(i, A)); } /// @brief Extract the alignment for a call or parameter (0=unknown). @@ -211,32 +211,32 @@ public: bool doesNotAccessMemory() const { CALLSITE_DELEGATE_GETTER(doesNotAccessMemory()); } - void setDoesNotAccessMemory(bool doesNotAccessMemory = true) { - CALLSITE_DELEGATE_SETTER(setDoesNotAccessMemory(doesNotAccessMemory)); + void setDoesNotAccessMemory() { + CALLSITE_DELEGATE_SETTER(setDoesNotAccessMemory()); } /// @brief Determine if the call does not access or only reads memory. bool onlyReadsMemory() const { CALLSITE_DELEGATE_GETTER(onlyReadsMemory()); } - void setOnlyReadsMemory(bool onlyReadsMemory = true) { - CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory(onlyReadsMemory)); + void setOnlyReadsMemory() { + CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory()); } /// @brief Determine if the call cannot return. bool doesNotReturn() const { CALLSITE_DELEGATE_GETTER(doesNotReturn()); } - void setDoesNotReturn(bool doesNotReturn = true) { - CALLSITE_DELEGATE_SETTER(setDoesNotReturn(doesNotReturn)); + void setDoesNotReturn() { + CALLSITE_DELEGATE_SETTER(setDoesNotReturn()); } /// @brief Determine if the call cannot unwind. bool doesNotThrow() const { CALLSITE_DELEGATE_GETTER(doesNotThrow()); } - void setDoesNotThrow(bool doesNotThrow = true) { - CALLSITE_DELEGATE_SETTER(setDoesNotThrow(doesNotThrow)); + void setDoesNotThrow() { + CALLSITE_DELEGATE_SETTER(setDoesNotThrow()); } #undef CALLSITE_DELEGATE_GETTER diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 3aab436..0c71882 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -15,6 +15,7 @@ #ifndef LLVM_SUPPORT_CASTING_H #define LLVM_SUPPORT_CASTING_H +#include "llvm/Support/type_traits.h" #include <cassert> namespace llvm { @@ -44,13 +45,23 @@ template<typename From> struct simplify_type<const From> { // The core of the implementation of isa<X> is here; To and From should be // the names of classes. This template can be specialized to customize the // implementation of isa<> without rewriting it from scratch. -template <typename To, typename From> +template <typename To, typename From, typename Enabler = void> struct isa_impl { static inline bool doit(const From &Val) { return To::classof(&Val); } }; +/// \brief Always allow upcasts, and perform no dynamic check for them. +template <typename To, typename From> +struct isa_impl<To, From, + typename llvm::enable_if_c< + llvm::is_base_of<To, From>::value + >::type + > { + static inline bool doit(const From &) { return true; } +}; + template <typename To, typename From> struct isa_impl_cl { static inline bool doit(const From &Val) { return isa_impl<To, From>::doit(Val); @@ -65,18 +76,21 @@ template <typename To, typename From> struct isa_impl_cl<To, const From> { template <typename To, typename From> struct isa_impl_cl<To, From*> { static inline bool doit(const From *Val) { + assert(Val && "isa<> used on a null pointer"); return isa_impl<To, From>::doit(*Val); } }; template <typename To, typename From> struct isa_impl_cl<To, const From*> { static inline bool doit(const From *Val) { + assert(Val && "isa<> used on a null pointer"); return isa_impl<To, From>::doit(*Val); } }; template <typename To, typename From> struct isa_impl_cl<To, const From*const> { static inline bool doit(const From *Val) { + assert(Val && "isa<> used on a null pointer"); return isa_impl<To, From>::doit(*Val); } }; diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index ae1570d..0ab39fc 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -20,10 +20,10 @@ #ifndef LLVM_SUPPORT_COMMANDLINE_H #define LLVM_SUPPORT_COMMANDLINE_H -#include "llvm/Support/type_traits.h" -#include "llvm/Support/Compiler.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/type_traits.h" #include <cassert> #include <climits> #include <cstdarg> @@ -41,16 +41,14 @@ namespace cl { // ParseCommandLineOptions - Command line option processing entry point. // void ParseCommandLineOptions(int argc, const char * const *argv, - const char *Overview = 0, - bool ReadResponseFiles = false); + const char *Overview = 0); //===----------------------------------------------------------------------===// // ParseEnvironmentOptions - Environment variable option processing alternate // entry point. // void ParseEnvironmentOptions(const char *progName, const char *envvar, - const char *Overview = 0, - bool ReadResponseFiles = false); + const char *Overview = 0); ///===---------------------------------------------------------------------===// /// SetVersionPrinter - Override the default (LLVM specific) version printer @@ -1509,7 +1507,7 @@ class bits : public Option, public bits_storage<DataType, Storage> { typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) return true; // Parse Error! - addValue(Val); + this->addValue(Val); setPosition(pos); Positions.push_back(pos); return false; @@ -1608,15 +1606,16 @@ public: class alias : public Option { Option *AliasFor; virtual bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Arg) { + StringRef Arg) LLVM_OVERRIDE { return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); } // Handle printing stuff... - virtual size_t getOptionWidth() const; - virtual void printOptionInfo(size_t GlobalWidth) const; + virtual size_t getOptionWidth() const LLVM_OVERRIDE; + virtual void printOptionInfo(size_t GlobalWidth) const LLVM_OVERRIDE; // Aliases do not need to print their values. - virtual void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const {} + virtual void printOptionValue(size_t /*GlobalWidth*/, + bool /*Force*/) const LLVM_OVERRIDE {} void done() { if (!hasArgStr()) diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 1136ff7..b32939e 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -19,28 +19,50 @@ # define __has_feature(x) 0 #endif -/// LLVM_HAS_RVALUE_REFERENCES - Does the compiler provide r-value references? +/// \brief Does the compiler support r-value references? /// This implies that <utility> provides the one-argument std::move; it /// does not imply the existence of any other C++ library features. #if (__has_feature(cxx_rvalue_references) \ || defined(__GXX_EXPERIMENTAL_CXX0X__) \ || (defined(_MSC_VER) && _MSC_VER >= 1600)) -#define LLVM_USE_RVALUE_REFERENCES 1 +#define LLVM_HAS_RVALUE_REFERENCES 1 #else -#define LLVM_USE_RVALUE_REFERENCES 0 +#define LLVM_HAS_RVALUE_REFERENCES 0 +#endif + +/// \brief Does the compiler support r-value reference *this? +/// +/// Sadly, this is separate from just r-value reference support because GCC +/// implemented everything but this thus far. No release of GCC yet has support +/// for this feature so it is enabled with Clang only. +/// FIXME: This should change to a version check when GCC grows support for it. +#if __has_feature(cxx_rvalue_references) +#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 +#else +#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 #endif /// llvm_move - Expands to ::std::move if the compiler supports /// r-value references; otherwise, expands to the argument. -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES #define llvm_move(value) (::std::move(value)) #else #define llvm_move(value) (value) #endif +/// Expands to '&' if r-value references are supported. +/// +/// This can be used to provide l-value/r-value overrides of member functions. +/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS +#if LLVM_HAS_RVALUE_REFERENCE_THIS +#define LLVM_LVALUE_FUNCTION & +#else +#define LLVM_LVALUE_FUNCTION +#endif + /// LLVM_DELETED_FUNCTION - Expands to = delete if the compiler supports it. /// Use to mark functions as uncallable. Member functions with this should -/// be declared private so that some behaivor is kept in C++03 mode. +/// be declared private so that some behavior is kept in C++03 mode. /// /// class DontCopy { /// private: @@ -57,6 +79,22 @@ #define LLVM_DELETED_FUNCTION #endif +/// LLVM_FINAL - Expands to 'final' if the compiler supports it. +/// Use to mark classes or virtual methods as final. +#if (__has_feature(cxx_override_control)) +#define LLVM_FINAL final +#else +#define LLVM_FINAL +#endif + +/// LLVM_OVERRIDE - Expands to 'override' if the compiler supports it. +/// Use to mark virtual methods as overriding a base class method. +#if (__has_feature(cxx_override_control)) +#define LLVM_OVERRIDE override +#else +#define LLVM_OVERRIDE +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and @@ -113,7 +151,6 @@ #define LLVM_UNLIKELY(EXPR) (EXPR) #endif - // C++ doesn't support 'extern template' of template specializations. GCC does, // but requires __extension__ before it. In the header, use this: // EXTERN_TEMPLATE_INSTANTIATION(class foo<bar>); @@ -127,8 +164,8 @@ #define TEMPLATE_INSTANTIATION(X) #endif -// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, -// mark a method "not for inlining". +/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, +/// mark a method "not for inlining". #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) #define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) #elif defined(_MSC_VER) @@ -137,10 +174,10 @@ #define LLVM_ATTRIBUTE_NOINLINE #endif -// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do -// so, mark a method "always inline" because it is performance sensitive. GCC -// 3.4 supported this but is buggy in various cases and produces unimplemented -// errors, just use it in GCC 4.0 and later. +/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do +/// so, mark a method "always inline" because it is performance sensitive. GCC +/// 3.4 supported this but is buggy in various cases and produces unimplemented +/// errors, just use it in GCC 4.0 and later. #if __GNUC__ > 3 #define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) #elif defined(_MSC_VER) @@ -149,7 +186,6 @@ #define LLVM_ATTRIBUTE_ALWAYS_INLINE #endif - #ifdef __GNUC__ #define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) #elif defined(_MSC_VER) @@ -158,8 +194,8 @@ #define LLVM_ATTRIBUTE_NORETURN #endif -// LLVM_EXTENSION - Support compilers where we have a keyword to suppress -// pedantic diagnostics. +/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress +/// pedantic diagnostics. #ifdef __GNUC__ #define LLVM_EXTENSION __extension__ #else @@ -181,16 +217,18 @@ decl #endif -// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands -// to an expression which states that it is undefined behavior for the -// compiler to reach this point. Otherwise is not defined. +/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands +/// to an expression which states that it is undefined behavior for the +/// compiler to reach this point. Otherwise is not defined. #if defined(__clang__) || (__GNUC__ > 4) \ || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) # define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) +# define LLVM_BUILTIN_UNREACHABLE __assume(false) #endif -// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression -// which causes the program to exit abnormally. +/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression +/// which causes the program to exit abnormally. #if defined(__clang__) || (__GNUC__ > 4) \ || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) # define LLVM_BUILTIN_TRAP __builtin_trap() @@ -198,4 +236,17 @@ # define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 #endif +/// \macro LLVM_ASSUME_ALIGNED +/// \brief Returns a pointer with an assumed alignment. +#if !defined(__clang__) && ((__GNUC__ > 4) \ + || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) +// FIXME: Enable on clang when it supports it. +# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) +#elif defined(LLVM_BUILTIN_UNREACHABLE) +# define LLVM_ASSUME_ALIGNED(p, a) \ + (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) +#else +# define LLVM_ASSUME_ALIGNED(p, a) (p) +#endif + #endif diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/Support/ConstantFolder.h index 93aa343..4aad952 100644 --- a/include/llvm/Support/ConstantFolder.h +++ b/include/llvm/Support/ConstantFolder.h @@ -17,8 +17,8 @@ #ifndef LLVM_SUPPORT_CONSTANTFOLDER_H #define LLVM_SUPPORT_CONSTANTFOLDER_H -#include "llvm/Constants.h" -#include "llvm/InstrTypes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/InstrTypes.h" namespace llvm { diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index 8d880fd..a3ae782 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -10,6 +10,7 @@ #ifndef LLVM_SUPPORT_DATAEXTRACTOR_H #define LLVM_SUPPORT_DATAEXTRACTOR_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/DataFlow.h b/include/llvm/Support/DataFlow.h index 355c402..a09ccaa 100644 --- a/include/llvm/Support/DataFlow.h +++ b/include/llvm/Support/DataFlow.h @@ -14,8 +14,8 @@ #ifndef LLVM_SUPPORT_DATAFLOW_H #define LLVM_SUPPORT_DATAFLOW_H -#include "llvm/User.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/IR/User.h" namespace llvm { diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 8f18a99..c703da5 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -37,7 +37,7 @@ enum { namespace dwarf { //===----------------------------------------------------------------------===// -// Dwarf constants as gleaned from the DWARF Debugging Information Format V.3 +// Dwarf constants as gleaned from the DWARF Debugging Information Format V.4 // reference manual http://dwarf.freestandards.org . // @@ -50,8 +50,6 @@ enum llvm_dwarf_constants { DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. DW_TAG_arg_variable = 0x101, // Tag for argument variables. - DW_TAG_return_variable = 0x102, // Tag for return variables. - DW_TAG_vector_type = 0x103, // Tag for vector types. DW_TAG_user_base = 0x1000, // Recommended base for user tags. @@ -231,6 +229,10 @@ enum dwarf_constants { DW_AT_const_expr = 0x6c, DW_AT_enum_class = 0x6d, DW_AT_linkage_name = 0x6e, + + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff, + DW_AT_MIPS_loop_begin = 0x2002, DW_AT_MIPS_tail_loop_begin = 0x2003, DW_AT_MIPS_epilog_begin = 0x2004, @@ -246,6 +248,12 @@ enum dwarf_constants { DW_AT_MIPS_ptr_dopetype = 0x200e, DW_AT_MIPS_allocatable_dopetype = 0x200f, DW_AT_MIPS_assumed_shape_dopetype = 0x2010, + + // This one appears to have only been implemented by Open64 for + // fortran and may conflict with other extensions. + DW_AT_MIPS_assumed_size = 0x2011, + + // GNU extensions DW_AT_sf_names = 0x2101, DW_AT_src_info = 0x2102, DW_AT_mac_info = 0x2103, @@ -254,9 +262,14 @@ enum dwarf_constants { DW_AT_body_end = 0x2106, DW_AT_GNU_vector = 0x2107, DW_AT_GNU_template_name = 0x2110, - DW_AT_MIPS_assumed_size = 0x2011, - DW_AT_lo_user = 0x2000, - DW_AT_hi_user = 0x3fff, + + // Extensions for Fission proposal. + DW_AT_GNU_dwo_name = 0x2130, + DW_AT_GNU_dwo_id = 0x2131, + DW_AT_GNU_ranges_base = 0x2132, + DW_AT_GNU_addr_base = 0x2133, + DW_AT_GNU_pubnames = 0x2134, + DW_AT_GNU_pubtypes = 0x2135, // Apple extensions. DW_AT_APPLE_optimized = 0x3fe1, @@ -300,6 +313,10 @@ enum dwarf_constants { DW_FORM_flag_present = 0x19, DW_FORM_ref_sig8 = 0x20, + // Extensions for Fission proposal + DW_FORM_GNU_addr_index = 0x1f01, + DW_FORM_GNU_str_index = 0x1f02, + // Operation encodings DW_OP_addr = 0x03, DW_OP_deref = 0x06, @@ -458,6 +475,10 @@ enum dwarf_constants { DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, + // Extensions for Fission proposal. + DW_OP_GNU_addr_index = 0xfb, + DW_OP_GNU_const_index = 0xfc, + // Encoding attribute values DW_ATE_address = 0x01, DW_ATE_boolean = 0x02, diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 0e1cfac..d6e54be 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -441,6 +441,7 @@ enum { R_MICROBLAZE_COPY = 21 }; +// ELF Relocation types for PPC32 enum { R_PPC_NONE = 0, /* No relocation. */ R_PPC_ADDR32 = 1, @@ -456,7 +457,39 @@ enum { R_PPC_REL14 = 11, R_PPC_REL14_BRTAKEN = 12, R_PPC_REL14_BRNTAKEN = 13, - R_PPC_REL32 = 26 + R_PPC_REL32 = 26, + R_PPC_TPREL16_LO = 70, + R_PPC_TPREL16_HA = 72 +}; + +// ELF Relocation types for PPC64 +enum { + R_PPC64_ADDR32 = 1, + R_PPC64_ADDR16_LO = 4, + R_PPC64_ADDR16_HI = 5, + R_PPC64_ADDR14 = 7, + R_PPC64_REL24 = 10, + R_PPC64_ADDR64 = 38, + R_PPC64_ADDR16_HIGHER = 39, + R_PPC64_ADDR16_HIGHEST = 41, + R_PPC64_REL64 = 44, + R_PPC64_TOC16 = 47, + R_PPC64_TOC16_LO = 48, + R_PPC64_TOC16_HA = 50, + R_PPC64_TOC = 51, + R_PPC64_TOC16_DS = 63, + R_PPC64_TOC16_LO_DS = 64, + R_PPC64_TLS = 67, + R_PPC64_DTPREL16_LO = 75, + R_PPC64_DTPREL16_HA = 77, + R_PPC64_GOT_TLSGD16_LO = 80, + R_PPC64_GOT_TLSGD16_HA = 82, + R_PPC64_GOT_TLSLD16_LO = 84, + R_PPC64_GOT_TLSLD16_HA = 86, + R_PPC64_GOT_TPREL16_LO_DS = 88, + R_PPC64_GOT_TPREL16_HA = 90, + R_PPC64_TLSGD = 107, + R_PPC64_TLSLD = 108 }; // ARM Specific e_flags @@ -674,8 +707,36 @@ enum { R_MIPS_NUM = 218 }; +// Hexagon Specific e_flags +// Release 5 ABI +enum { + // Object processor version flags, bits[3:0] + EF_HEXAGON_MACH_V2 = 0x00000001, // Hexagon V2 + EF_HEXAGON_MACH_V3 = 0x00000002, // Hexagon V3 + EF_HEXAGON_MACH_V4 = 0x00000003, // Hexagon V4 + EF_HEXAGON_MACH_V5 = 0x00000004, // Hexagon V5 + + // Highest ISA version flags + EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[3:0] + // of e_flags + EF_HEXAGON_ISA_V2 = 0x00000010, // Hexagon V2 ISA + EF_HEXAGON_ISA_V3 = 0x00000020, // Hexagon V3 ISA + EF_HEXAGON_ISA_V4 = 0x00000030, // Hexagon V4 ISA + EF_HEXAGON_ISA_V5 = 0x00000040 // Hexagon V5 ISA +}; + +// Hexagon specific Section indexes for common small data +// Release 5 ABI +enum { + SHN_HEXAGON_SCOMMON = 0xff00, // Other access sizes + SHN_HEXAGON_SCOMMON_1 = 0xff01, // Byte-sized access + SHN_HEXAGON_SCOMMON_2 = 0xff02, // Half-word-sized access + SHN_HEXAGON_SCOMMON_4 = 0xff03, // Word-sized access + SHN_HEXAGON_SCOMMON_8 = 0xff04 // Double-word-size access +}; + // ELF Relocation types for Hexagon -// Release 5 ABI - Document: 80-V9418-3 Rev. J +// Release 5 ABI enum { R_HEX_NONE = 0, R_HEX_B22_PCREL = 1, @@ -1104,6 +1165,9 @@ enum { PT_PHDR = 6, // The program header table itself. PT_TLS = 7, // The thread-local storage template. PT_LOOS = 0x60000000, // Lowest operating system-specific pt entry type. + PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. + PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. + PT_HIPROC = 0x7fffffff, // Highest processor-specific program hdr entry type. // x86-64 program header types. // These all contain stack unwind tables. @@ -1114,9 +1178,11 @@ enum { PT_GNU_STACK = 0x6474e551, // Indicates stack executability. PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. - PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. - PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. - PT_HIPROC = 0x7fffffff // Highest processor-specific program hdr entry type. + // ARM program header types. + PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility information + // These all contain stack unwind tables. + PT_ARM_EXIDX = 0x70000001, + PT_ARM_UNWIND = 0x70000001 }; // Segment flag bits. diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 8d5649d..d438fac 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -14,136 +14,78 @@ #ifndef LLVM_SUPPORT_ENDIAN_H #define LLVM_SUPPORT_ENDIAN_H +#include "llvm/Support/AlignOf.h" #include "llvm/Support/Host.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/type_traits.h" namespace llvm { namespace support { +enum endianness {big, little, native}; -enum endianness {big, little}; -enum alignment {unaligned, aligned}; +// These are named values for common alignments. +enum {aligned = 0, unaligned = 1}; namespace detail { - -template<typename value_type, alignment align> -struct alignment_access_helper; - -template<typename value_type> -struct alignment_access_helper<value_type, aligned> -{ - value_type val; -}; - -// Provides unaligned loads and stores. -#pragma pack(push) -#pragma pack(1) -template<typename value_type> -struct alignment_access_helper<value_type, unaligned> -{ - value_type val; -}; -#pragma pack(pop) - + /// \brief ::value is either alignment, or alignof(T) if alignment is 0. + template<class T, int alignment> + struct PickAlignment { + enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment}; + }; } // end namespace detail namespace endian { - template<typename value_type, alignment align> - inline value_type read_le(const void *memory) { - value_type t = - reinterpret_cast<const detail::alignment_access_helper - <value_type, align> *>(memory)->val; - if (sys::isBigEndianHost()) - return sys::SwapByteOrder(t); - return t; - } - - template<typename value_type, alignment align> - inline void write_le(void *memory, value_type value) { - if (sys::isBigEndianHost()) - value = sys::SwapByteOrder(value); - reinterpret_cast<detail::alignment_access_helper<value_type, align> *> - (memory)->val = value; - } +template<typename value_type, endianness endian> +inline value_type byte_swap(value_type value) { + if (endian != native && sys::isBigEndianHost() != (endian == big)) + return sys::SwapByteOrder(value); + return value; +} - template<typename value_type, alignment align> - inline value_type read_be(const void *memory) { - value_type t = - reinterpret_cast<const detail::alignment_access_helper - <value_type, align> *>(memory)->val; - if (sys::isLittleEndianHost()) - return sys::SwapByteOrder(t); - return t; - } +template<typename value_type, + endianness endian, + std::size_t alignment> +inline value_type read(const void *memory) { + value_type ret; + + memcpy(&ret, + LLVM_ASSUME_ALIGNED(memory, + (detail::PickAlignment<value_type, alignment>::value)), + sizeof(value_type)); + return byte_swap<value_type, endian>(ret); +} - template<typename value_type, alignment align> - inline void write_be(void *memory, value_type value) { - if (sys::isLittleEndianHost()) - value = sys::SwapByteOrder(value); - reinterpret_cast<detail::alignment_access_helper<value_type, align> *> - (memory)->val = value; - } +template<typename value_type, + endianness endian, + std::size_t alignment> +inline void write(void *memory, value_type value) { + value = byte_swap<value_type, endian>(value); + memcpy(LLVM_ASSUME_ALIGNED(memory, + (detail::PickAlignment<value_type, alignment>::value)), + &value, + sizeof(value_type)); } +} // end namespace endian namespace detail { - template<typename value_type, endianness endian, - alignment align> -class packed_endian_specific_integral; - -template<typename value_type> -class packed_endian_specific_integral<value_type, little, unaligned> { -public: - operator value_type() const { - return endian::read_le<value_type, unaligned>(Value); - } - void operator=(value_type newValue) { - endian::write_le<value_type, unaligned>((void *)&Value, newValue); - } -private: - uint8_t Value[sizeof(value_type)]; -}; - -template<typename value_type> -class packed_endian_specific_integral<value_type, big, unaligned> { -public: + std::size_t alignment> +struct packed_endian_specific_integral { operator value_type() const { - return endian::read_be<value_type, unaligned>(Value); + return endian::read<value_type, endian, alignment>( + (const void*)Value.buffer); } - void operator=(value_type newValue) { - endian::write_be<value_type, unaligned>((void *)&Value, newValue); - } -private: - uint8_t Value[sizeof(value_type)]; -}; -template<typename value_type> -class packed_endian_specific_integral<value_type, little, aligned> { -public: - operator value_type() const { - return endian::read_le<value_type, aligned>(&Value); - } void operator=(value_type newValue) { - endian::write_le<value_type, aligned>((void *)&Value, newValue); + endian::write<value_type, endian, alignment>( + (void*)Value.buffer, newValue); } -private: - value_type Value; -}; -template<typename value_type> -class packed_endian_specific_integral<value_type, big, aligned> { -public: - operator value_type() const { - return endian::read_be<value_type, aligned>(&Value); - } - void operator=(value_type newValue) { - endian::write_be<value_type, aligned>((void *)&Value, newValue); - } private: - value_type Value; + AlignedCharArray<PickAlignment<value_type, alignment>::value, + sizeof(value_type)> Value; }; - } // end namespace detail typedef detail::packed_endian_specific_integral @@ -218,6 +160,19 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral <int64_t, big, aligned> aligned_big64_t; +typedef detail::packed_endian_specific_integral + <uint16_t, native, unaligned> unaligned_uint16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, native, unaligned> unaligned_uint32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, native, unaligned> unaligned_uint64_t; + +typedef detail::packed_endian_specific_integral + <int16_t, native, unaligned> unaligned_int16_t; +typedef detail::packed_endian_specific_integral + <int32_t, native, unaligned> unaligned_int32_t; +typedef detail::packed_endian_specific_integral + <int64_t, native, unaligned> unaligned_int64_t; } // end namespace llvm } // end namespace support diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index 95b0109..ca5dec0 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -15,8 +15,8 @@ #ifndef LLVM_SUPPORT_ERRORHANDLING_H #define LLVM_SUPPORT_ERRORHANDLING_H -#include "llvm/Support/Compiler.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include <string> namespace llvm { diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index 0f07164..cbc9c46 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -14,84 +14,79 @@ #ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H #define LLVM_SUPPORT_FILEOUTPUTBUFFER_H +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/FileSystem.h" namespace llvm { - class error_code; -template<class T> class OwningPtr; /// FileOutputBuffer - This interface provides simple way to create an in-memory -/// buffer which will be written to a file. During the lifetime of these +/// buffer which will be written to a file. During the lifetime of these /// objects, the content or existence of the specified file is undefined. That /// is, creating an OutputBuffer for a file may immediately remove the file. -/// If the FileOutputBuffer is committed, the target file's content will become -/// the buffer content at the time of the commit. If the FileOutputBuffer is +/// If the FileOutputBuffer is committed, the target file's content will become +/// the buffer content at the time of the commit. If the FileOutputBuffer is /// not committed, the file will be deleted in the FileOutputBuffer destructor. class FileOutputBuffer { public: enum { F_executable = 1 /// set the 'x' bit on the resulting file - }; + }; /// Factory method to create an OutputBuffer object which manages a read/write /// buffer of the specified size. When committed, the buffer will be written - /// to the file at the specified path. - static error_code create(StringRef FilePath, size_t Size, - OwningPtr<FileOutputBuffer> &Result, - unsigned Flags=0); - + /// to the file at the specified path. + static error_code create(StringRef FilePath, size_t Size, + OwningPtr<FileOutputBuffer> &Result, + unsigned Flags = 0); /// Returns a pointer to the start of the buffer. - uint8_t *getBufferStart() const { - return BufferStart; + uint8_t *getBufferStart() { + return (uint8_t*)Region->data(); } - + /// Returns a pointer to the end of the buffer. - uint8_t *getBufferEnd() const { - return BufferEnd; + uint8_t *getBufferEnd() { + return (uint8_t*)Region->data() + Region->size(); } - + /// Returns size of the buffer. size_t getBufferSize() const { - return BufferEnd - BufferStart; + return Region->size(); } - + /// Returns path where file will show up if buffer is committed. StringRef getPath() const { return FinalPath; } - - /// Flushes the content of the buffer to its file and deallocates the + + /// Flushes the content of the buffer to its file and deallocates the /// buffer. If commit() is not called before this object's destructor /// is called, the file is deleted in the destructor. The optional parameter /// is used if it turns out you want the file size to be smaller than /// initially requested. error_code commit(int64_t NewSmallerSize = -1); - + /// If this object was previously committed, the destructor just deletes /// this object. If this object was not committed, the destructor /// deallocates the buffer and the target file is never written. ~FileOutputBuffer(); - -protected: - FileOutputBuffer(const FileOutputBuffer &); // DO NOT IMPLEMENT - FileOutputBuffer &operator=(const FileOutputBuffer &); // DO NOT IMPLEMENT - FileOutputBuffer(uint8_t *Start, uint8_t *End, - StringRef Path, StringRef TempPath); - - uint8_t *BufferStart; - uint8_t *BufferEnd; +private: + FileOutputBuffer(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; + FileOutputBuffer &operator=(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; + + FileOutputBuffer(llvm::sys::fs::mapped_file_region *R, + StringRef Path, StringRef TempPath); + + OwningPtr<llvm::sys::fs::mapped_file_region> Region; SmallString<128> FinalPath; SmallString<128> TempPath; }; - - - } // end namespace llvm #endif diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 5d60205..f1cbe97 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -280,7 +280,7 @@ error_code create_symlink(const Twine &to, const Twine &from); /// @brief Get the current path. /// /// @param result Holds the current path on return. -/// @results errc::success if the current path has been stored in result, +/// @returns errc::success if the current path has been stored in result, /// otherwise a platform specific error_code. error_code current_path(SmallVectorImpl<char> &result); @@ -289,7 +289,7 @@ error_code current_path(SmallVectorImpl<char> &result); /// @param path Input path. /// @param existed Set to true if \a path existed, false if it did not. /// undefined otherwise. -/// @results errc::success if path has been removed and existed has been +/// @returns errc::success if path has been removed and existed has been /// successfully set, otherwise a platform specific error_code. error_code remove(const Twine &path, bool &existed); @@ -298,7 +298,7 @@ error_code remove(const Twine &path, bool &existed); /// /// @param path Input path. /// @param num_removed Number of files removed. -/// @results errc::success if path has been removed and num_removed has been +/// @returns errc::success if path has been removed and num_removed has been /// successfully set, otherwise a platform specific error_code. error_code remove_all(const Twine &path, uint32_t &num_removed); @@ -323,7 +323,7 @@ error_code resize_file(const Twine &path, uint64_t size); /// @brief Does file exist? /// /// @param status A file_status previously returned from stat. -/// @results True if the file represented by status exists, false if it does +/// @returns True if the file represented by status exists, false if it does /// not. bool exists(file_status status); @@ -332,7 +332,7 @@ bool exists(file_status status); /// @param path Input path. /// @param result Set to true if the file represented by status exists, false if /// it does not. Undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code exists(const Twine &path, bool &result); @@ -350,7 +350,7 @@ inline bool exists(const Twine &path) { /// /// assert(status_known(A) || status_known(B)); /// -/// @results True if A and B both represent the same file system entity, false +/// @returns True if A and B both represent the same file system entity, false /// otherwise. bool equivalent(file_status A, file_status B); @@ -362,7 +362,7 @@ bool equivalent(file_status A, file_status B); /// @param B Input path B. /// @param result Set to true if stat(A) and stat(B) have the same device and /// inode (or equivalent). -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code equivalent(const Twine &A, const Twine &B, bool &result); @@ -384,7 +384,7 @@ error_code file_size(const Twine &path, uint64_t &result); /// @brief Does status represent a directory? /// /// @param status A file_status previously returned from status. -/// @results status.type() == file_type::directory_file. +/// @returns status.type() == file_type::directory_file. bool is_directory(file_status status); /// @brief Is path a directory? @@ -392,14 +392,14 @@ bool is_directory(file_status status); /// @param path Input path. /// @param result Set to true if \a path is a directory, false if it is not. /// Undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code is_directory(const Twine &path, bool &result); /// @brief Does status represent a regular file? /// /// @param status A file_status previously returned from status. -/// @results status_known(status) && status.type() == file_type::regular_file. +/// @returns status_known(status) && status.type() == file_type::regular_file. bool is_regular_file(file_status status); /// @brief Is path a regular file? @@ -407,7 +407,7 @@ bool is_regular_file(file_status status); /// @param path Input path. /// @param result Set to true if \a path is a regular file, false if it is not. /// Undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code is_regular_file(const Twine &path, bool &result); @@ -415,7 +415,7 @@ error_code is_regular_file(const Twine &path, bool &result); /// directory, regular file, or symlink? /// /// @param status A file_status previously returned from status. -/// @results exists(s) && !is_regular_file(s) && !is_directory(s) && +/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) && /// !is_symlink(s) bool is_other(file_status status); @@ -425,7 +425,7 @@ bool is_other(file_status status); /// @param path Input path. /// @param result Set to true if \a path exists, but is not a directory, regular /// file, or a symlink, false if it does not. Undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code is_other(const Twine &path, bool &result); @@ -440,7 +440,7 @@ bool is_symlink(file_status status); /// @param path Input path. /// @param result Set to true if \a path is a symlink, false if it is not. /// Undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code is_symlink(const Twine &path, bool &result); @@ -448,28 +448,28 @@ error_code is_symlink(const Twine &path, bool &result); /// /// @param path Input path. /// @param result Set to the file status. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code status(const Twine &path, file_status &result); /// @brief Modifies permission bits on a file /// /// @param path Input path. -/// @results errc::success if permissions have been changed, otherwise a +/// @returns errc::success if permissions have been changed, otherwise a /// platform specific error_code. error_code permissions(const Twine &path, perms prms); /// @brief Is status available? /// /// @param s Input file status. -/// @results True if status() != status_error. +/// @returns True if status() != status_error. bool status_known(file_status s); /// @brief Is status available? /// /// @param path Input path. /// @param result Set to true if status() != status_error. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code status_known(const Twine &path, bool &result); @@ -488,9 +488,9 @@ error_code status_known(const Twine &path, bool &result); /// @param model Name to base unique path off of. /// @param result_fd Set to the opened file's file descriptor. /// @param result_path Set to the opened file's absolute path. -/// @param makeAbsolute If true and @model is not an absolute path, a temp +/// @param makeAbsolute If true and \a model is not an absolute path, a temp /// directory will be prepended. -/// @results errc::success if result_{fd,path} have been successfully set, +/// @returns errc::success if result_{fd,path} have been successfully set, /// otherwise a platform specific error_code. error_code unique_file(const Twine &model, int &result_fd, SmallVectorImpl<char> &result_path, @@ -503,7 +503,7 @@ error_code unique_file(const Twine &model, int &result_fd, /// /// @param path Input path. /// @param result Set to the canonicalized version of \a path. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); @@ -511,7 +511,7 @@ error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); /// /// @param path Input path. /// @param magic Byte sequence to compare \a path's first len(magic) bytes to. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code has_magic(const Twine &path, const Twine &magic, bool &result); @@ -522,7 +522,7 @@ error_code has_magic(const Twine &path, const Twine &magic, bool &result); /// @param result Set to the first \a len bytes in the file pointed to by /// \a path. Or the entire file if file_size(path) < len, in which /// case result.size() returns the size of the file. -/// @results errc::success if result has been successfully set, +/// @returns errc::success if result has been successfully set, /// errc::value_too_large if len is larger then the file pointed to by /// \a path, otherwise a platform specific error_code. error_code get_magic(const Twine &path, uint32_t len, @@ -535,14 +535,14 @@ file_magic identify_magic(StringRef magic); /// /// @param path Input path. /// @param result Set to the type of file, or LLVMFileType::Unknown_FileType. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code identify_magic(const Twine &path, file_magic &result); /// @brief Get library paths the system linker uses. /// /// @param result Set to the list of system library paths. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); @@ -550,7 +550,7 @@ error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); /// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. /// /// @param result Set to the list of bitcode library paths. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); @@ -563,7 +563,7 @@ error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); /// /// @param short_name Library name one would give to the system linker. /// @param result Set to the absolute path \a short_name represents. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); @@ -572,7 +572,7 @@ error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); /// @param argv0 The program name as it was spelled on the command line. /// @param MainAddr Address of some symbol in the executable (not in a library). /// @param result Set to the absolute path of the current executable. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code GetMainExecutable(const char *argv0, void *MainAddr, SmallVectorImpl<char> &result); @@ -607,7 +607,7 @@ private: public: typedef char char_type; -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES mapped_file_region(mapped_file_region&&); mapped_file_region &operator =(mapped_file_region&&); #endif @@ -664,7 +664,7 @@ public: /// to the file. If false, the file will be mapped read-only /// and the buffer will be read-only. /// @param result Set to the start address of the mapped buffer. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, bool map_writable, void *&result); @@ -674,7 +674,7 @@ error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, /// /// @param base Pointer to the start of the buffer. /// @param size Byte length of the range to unmmap. -/// @results errc::success if result has been successfully set, otherwise a +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. error_code unmap_file_pages(void *base, size_t size); diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index 59812d9..aaa54e1 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -170,31 +170,47 @@ public: } }; -/// format - This is a helper function that is used to produce formatted output. -/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +/// This is a helper function that is used to produce formatted output. +/// +/// This is typically used like: +/// \code +/// OS << format("%0.4f", myfloat) << '\n'; +/// \endcode template <typename T> inline format_object1<T> format(const char *Fmt, const T &Val) { return format_object1<T>(Fmt, Val); } -/// format - This is a helper function that is used to produce formatted output. -/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +/// This is a helper function that is used to produce formatted output. +/// +/// This is typically used like: +/// \code +/// OS << format("%0.4f", myfloat) << '\n'; +/// \endcode template <typename T1, typename T2> inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1, const T2 &Val2) { return format_object2<T1, T2>(Fmt, Val1, Val2); } -/// format - This is a helper function that is used to produce formatted output. -/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +/// This is a helper function that is used to produce formatted output. +/// +/// This is typically used like: +/// \code +/// OS << format("%0.4f", myfloat) << '\n'; +/// \endcode template <typename T1, typename T2, typename T3> inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3) { return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3); } -/// format - This is a helper function that is used to produce formatted output. -/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +/// This is a helper function that is used to produce formatted output. +/// +/// This is typically used like: +/// \code +/// OS << format("%0.4f", myfloat) << '\n'; +/// \endcode template <typename T1, typename T2, typename T3, typename T4> inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, @@ -202,8 +218,12 @@ inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4); } -/// format - This is a helper function that is used to produce formatted output. -/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +/// This is a helper function that is used to produce formatted output. +/// +/// This is typically used like: +/// \code +/// OS << format("%0.4f", myfloat) << '\n'; +/// \endcode template <typename T1, typename T2, typename T3, typename T4, typename T5> inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, const T2 &Val2, const T3 &Val3, diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 58a1885..21635dc 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -55,14 +55,15 @@ namespace llvm /// const char *Scanned; - virtual void write_impl(const char *Ptr, size_t Size); + virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; /// current_pos - Return the current position within the stream, /// not counting the bytes currently in the buffer. - virtual uint64_t current_pos() const { - // This has the same effect as calling TheStream.current_pos(), - // but that interface is private. - return TheStream->tell() - TheStream->GetNumBytesInBuffer(); + virtual uint64_t current_pos() const LLVM_OVERRIDE { + // Our current position in the stream is all the contents which have been + // written to the underlying stream (*not* the current position of the + // underlying stream). + return TheStream->tell(); } /// ComputeColumn - Examine the given output buffer and figure out which diff --git a/include/llvm/Support/GetElementPtrTypeIterator.h b/include/llvm/Support/GetElementPtrTypeIterator.h index ef92c95..52b06ad 100644 --- a/include/llvm/Support/GetElementPtrTypeIterator.h +++ b/include/llvm/Support/GetElementPtrTypeIterator.h @@ -15,8 +15,8 @@ #ifndef LLVM_SUPPORT_GETELEMENTPTRTYPE_H #define LLVM_SUPPORT_GETELEMENTPTRTYPE_H -#include "llvm/User.h" -#include "llvm/DerivedTypes.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/User.h" namespace llvm { template<typename ItTy = User::const_op_iterator> @@ -83,15 +83,15 @@ namespace llvm { typedef generic_gep_type_iterator<> gep_type_iterator; inline gep_type_iterator gep_type_begin(const User *GEP) { - return gep_type_iterator::begin(GEP->getOperand(0)->getType(), - GEP->op_begin()+1); + return gep_type_iterator::begin + (GEP->getOperand(0)->getType()->getScalarType(), GEP->op_begin()+1); } inline gep_type_iterator gep_type_end(const User *GEP) { return gep_type_iterator::end(GEP->op_end()); } inline gep_type_iterator gep_type_begin(const User &GEP) { - return gep_type_iterator::begin(GEP.getOperand(0)->getType(), - GEP.op_begin()+1); + return gep_type_iterator::begin + (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1); } inline gep_type_iterator gep_type_end(const User &GEP) { return gep_type_iterator::end(GEP.op_end()); diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index f178b0c..30cfe61 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -23,12 +23,12 @@ #ifndef LLVM_SUPPORT_GRAPHWRITER_H #define LLVM_SUPPORT_GRAPHWRITER_H -#include "llvm/Support/DOTGraphTraits.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/Support/DOTGraphTraits.h" #include "llvm/Support/Path.h" -#include <vector> +#include "llvm/Support/raw_ostream.h" #include <cassert> +#include <vector> namespace llvm { diff --git a/include/llvm/Support/InstIterator.h b/include/llvm/Support/InstIterator.h index 7d3f883..ac936a1 100644 --- a/include/llvm/Support/InstIterator.h +++ b/include/llvm/Support/InstIterator.h @@ -19,8 +19,8 @@ #ifndef LLVM_SUPPORT_INSTITERATOR_H #define LLVM_SUPPORT_INSTITERATOR_H -#include "llvm/BasicBlock.h" -#include "llvm/Function.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" namespace llvm { diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h index bb9e769..9e5361c 100644 --- a/include/llvm/Support/IntegersSubset.h +++ b/include/llvm/Support/IntegersSubset.h @@ -18,12 +18,11 @@ #ifndef CONSTANTRANGESSET_H_ #define CONSTANTRANGESSET_H_ +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" #include <list> -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" - namespace llvm { // The IntItem is a wrapper for APInt. @@ -411,8 +410,8 @@ public: unsigned getSize() 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(); + const APInt Low = getItem(i).getLow(); + const APInt High = getItem(i).getHigh(); APInt S = High - Low + 1; sz += S; } @@ -426,8 +425,8 @@ public: 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(); + const APInt Low = getItem(i).getLow(); + const APInt High = getItem(i).getHigh(); APInt S = High - Low + 1; APInt oldSz = sz; sz += S; diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index 410edd4..b52e5bc 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -15,7 +15,7 @@ #ifndef LLVM_SYSTEM_LEB128_H #define LLVM_SYSTEM_LEB128_H -#include <llvm/Support/raw_ostream.h> +#include "llvm/Support/raw_ostream.h" namespace llvm { diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index e2fa8eb..8c4a760 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -47,8 +47,8 @@ private: Optional<std::pair<std::string, int> > Owner; Optional<error_code> Error; - LockFileManager(const LockFileManager &); - LockFileManager &operator=(const LockFileManager &); + LockFileManager(const LockFileManager &) LLVM_DELETED_FUNCTION; + LockFileManager &operator=(const LockFileManager &) LLVM_DELETED_FUNCTION; static Optional<std::pair<std::string, int> > readLockFile(StringRef LockFileName); diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 35c2694..11f9e63 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -431,21 +431,22 @@ inline uint64_t NextPowerOf2(uint64_t A) { return A + 1; } -/// RoundUpToAlignment - Returns the next integer (mod 2**64) that is -/// greater than or equal to \arg Value and is a multiple of \arg -/// Align. Align must be non-zero. +/// Returns the next integer (mod 2**64) that is greater than or equal to +/// \p Value and is a multiple of \p Align. \p Align must be non-zero. /// /// Examples: -/// RoundUpToAlignment(5, 8) = 8 -/// RoundUpToAlignment(17, 8) = 24 -/// RoundUpToAlignment(~0LL, 8) = 0 +/// \code +/// RoundUpToAlignment(5, 8) = 8 +/// RoundUpToAlignment(17, 8) = 24 +/// RoundUpToAlignment(~0LL, 8) = 0 +/// \endcode inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { return ((Value + Align - 1) / Align) * Align; } -/// OffsetToAlignment - Return the offset to the next integer (mod 2**64) that -/// is greater than or equal to \arg Value and is a multiple of \arg -/// Align. Align must be non-zero. +/// Returns the offset to the next integer (mod 2**64) that is greater than +/// or equal to \p Value and is a multiple of \p Align. \p Align must be +/// non-zero. inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { return RoundUpToAlignment(Value, Align) - Value; } diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h index 37890e7..025eee7 100644 --- a/include/llvm/Support/Memory.h +++ b/include/llvm/Support/Memory.h @@ -15,6 +15,7 @@ #define LLVM_SYSTEM_MEMORY_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/system_error.h" #include <string> namespace llvm { @@ -43,6 +44,70 @@ namespace sys { /// @brief An abstraction for memory operations. class Memory { public: + enum ProtectionFlags { + MF_READ = 0x1000000, + MF_WRITE = 0x2000000, + MF_EXEC = 0x4000000 + }; + + /// This method allocates a block of memory that is suitable for loading + /// dynamically generated code (e.g. JIT). An attempt to allocate + /// \p NumBytes bytes of virtual memory is made. + /// \p NearBlock may point to an existing allocation in which case + /// an attempt is made to allocate more memory near the existing block. + /// The actual allocated address is not guaranteed to be near the requested + /// address. + /// \p Flags is used to set the initial protection flags for the block + /// of the memory. + /// \p EC [out] returns an object describing any error that occurs. + /// + /// This method may allocate more than the number of bytes requested. The + /// actual number of bytes allocated is indicated in the returned + /// MemoryBlock. + /// + /// The start of the allocated block must be aligned with the + /// system allocation granularity (64K on Windows, page size on Linux). + /// If the address following \p NearBlock is not so aligned, it will be + /// rounded up to the next allocation granularity boundary. + /// + /// \r a non-null MemoryBlock if the function was successful, + /// otherwise a null MemoryBlock is with \p EC describing the error. + /// + /// @brief Allocate mapped memory. + static MemoryBlock allocateMappedMemory(size_t NumBytes, + const MemoryBlock *const NearBlock, + unsigned Flags, + error_code &EC); + + /// This method releases a block of memory that was allocated with the + /// allocateMappedMemory method. It should not be used to release any + /// memory block allocated any other way. + /// \p Block describes the memory to be released. + /// + /// \r error_success if the function was successful, or an error_code + /// describing the failure if an error occurred. + /// + /// @brief Release mapped memory. + static error_code releaseMappedMemory(MemoryBlock &Block); + + /// This method sets the protection flags for a block of memory to the + /// state specified by /p Flags. The behavior is not specified if the + /// memory was not allocated using the allocateMappedMemory method. + /// \p Block describes the memory block to be protected. + /// \p Flags specifies the new protection state to be assigned to the block. + /// \p ErrMsg [out] returns a string describing any error that occured. + /// + /// If \p Flags is MF_WRITE, the actual behavior varies + /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the + /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). + /// + /// \r error_success if the function was successful, or an error_code + /// describing the failure if an error occurred. + /// + /// @brief Set memory protection state. + static error_code protectMappedMemory(const MemoryBlock &Block, + unsigned Flags); + /// This method allocates a block of Read/Write/Execute memory that is /// suitable for executing dynamically generated code (e.g. JIT). An /// attempt to allocate \p NumBytes bytes of virtual memory is made. diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 06816de..1f02907 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -15,6 +15,7 @@ #define LLVM_SUPPORT_MEMORYBUFFER_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -36,8 +37,8 @@ class MemoryBuffer { const char *BufferStart; // Start of the buffer. const char *BufferEnd; // End of the buffer. - MemoryBuffer(const MemoryBuffer &); // DO NOT IMPLEMENT - MemoryBuffer &operator=(const MemoryBuffer &); // DO NOT IMPLEMENT + MemoryBuffer(const MemoryBuffer &) LLVM_DELETED_FUNCTION; + MemoryBuffer &operator=(const MemoryBuffer &) LLVM_DELETED_FUNCTION; protected: MemoryBuffer() {} void init(const char *BufStart, const char *BufEnd, diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h index 42ea630..6abc533 100644 --- a/include/llvm/Support/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -14,6 +14,7 @@ #ifndef LLVM_SYSTEM_MUTEX_H #define LLVM_SYSTEM_MUTEX_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/Threading.h" #include <cassert> @@ -75,8 +76,8 @@ namespace llvm /// @name Do Not Implement /// @{ private: - MutexImpl(const MutexImpl & original); - void operator=(const MutexImpl &); + MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION; + void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION; /// @} }; diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h index cd13bfe..6bb1622 100644 --- a/include/llvm/Support/MutexGuard.h +++ b/include/llvm/Support/MutexGuard.h @@ -26,8 +26,8 @@ namespace llvm { /// @brief Guard a section of code with a Mutex. class MutexGuard { sys::Mutex &M; - MutexGuard(const MutexGuard &); // DO NOT IMPLEMENT - void operator=(const MutexGuard &); // DO NOT IMPLEMENT + MutexGuard(const MutexGuard &) LLVM_DELETED_FUNCTION; + void operator=(const MutexGuard &) LLVM_DELETED_FUNCTION; public: MutexGuard(sys::Mutex &m) : M(m) { M.acquire(); } ~MutexGuard() { M.release(); } diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/Support/NoFolder.h index 8e41a64..ecfbbaa 100644 --- a/include/llvm/Support/NoFolder.h +++ b/include/llvm/Support/NoFolder.h @@ -23,8 +23,8 @@ #define LLVM_SUPPORT_NOFOLDER_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/Constants.h" -#include "llvm/Instructions.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" namespace llvm { diff --git a/include/llvm/Support/PassNameParser.h b/include/llvm/Support/PassNameParser.h index a24a6f0..bdfab39 100644 --- a/include/llvm/Support/PassNameParser.h +++ b/include/llvm/Support/PassNameParser.h @@ -23,8 +23,8 @@ #ifndef LLVM_SUPPORT_PASS_NAME_PARSER_H #define LLVM_SUPPORT_PASS_NAME_PARSER_H -#include "llvm/Pass.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/Support/PathV2.h b/include/llvm/Support/PathV2.h index 967ea1e..ae1a21c 100644 --- a/include/llvm/Support/PathV2.h +++ b/include/llvm/Support/PathV2.h @@ -39,13 +39,14 @@ namespace path { /// The backwards traversal order is the reverse of forward traversal. /// /// Iteration examples. Each component is separated by ',': -/// / => / -/// /foo => /,foo -/// foo/ => foo,. -/// /foo/bar => /,foo,bar -/// ../ => ..,. -/// C:\foo\bar => C:,/,foo,bar -/// +/// @code +/// / => / +/// /foo => /,foo +/// foo/ => foo,. +/// /foo/bar => /,foo,bar +/// ../ => ..,. +/// C:\foo\bar => C:,/,foo,bar +/// @endcode class const_iterator { StringRef Path; ///< The entire path. StringRef Component; ///< The current component. Not necessarily in Path. @@ -107,18 +108,22 @@ inline reverse_iterator rend(StringRef path) { /// @brief Remove the last component from \a path unless it is the root dir. /// -/// directory/filename.cpp => directory/ -/// directory/ => directory -/// / => / +/// @code +/// directory/filename.cpp => directory/ +/// directory/ => directory +/// / => / +/// @endcode /// /// @param path A path that is modified to not have a file component. void remove_filename(SmallVectorImpl<char> &path); /// @brief Replace the file extension of \a path with \a extension. /// -/// ./filename.cpp => ./filename.extension -/// ./filename => ./filename.extension -/// ./ => ./.extension +/// @code +/// ./filename.cpp => ./filename.extension +/// ./filename => ./filename.extension +/// ./ => ./.extension +/// @endcode /// /// @param path A path that has its extension replaced with \a extension. /// @param extension The extension to be added. It may be empty. It may also @@ -128,9 +133,11 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension); /// @brief Append to path. /// -/// /foo + bar/f => /foo/bar/f -/// /foo/ + bar/f => /foo/bar/f -/// foo + bar/f => foo/bar/f +/// @code +/// /foo + bar/f => /foo/bar/f +/// /foo/ + bar/f => /foo/bar/f +/// foo + bar/f => foo/bar/f +/// @endcode /// /// @param path Set to \a path + \a component. /// @param a The component to be appended to \a path. @@ -141,9 +148,11 @@ void append(SmallVectorImpl<char> &path, const Twine &a, /// @brief Append to path. /// -/// /foo + [bar,f] => /foo/bar/f -/// /foo/ + [bar,f] => /foo/bar/f -/// foo + [bar,f] => foo/bar/f +/// @code +/// /foo + [bar,f] => /foo/bar/f +/// /foo/ + [bar,f] => /foo/bar/f +/// foo + [bar,f] => foo/bar/f +/// @endcode /// /// @param path Set to \a path + [\a begin, \a end). /// @param begin Start of components to append. @@ -169,9 +178,11 @@ void native(const Twine &path, SmallVectorImpl<char> &result); /// @brief Get root name. /// -/// //net/hello => //net -/// c:/hello => c: (on Windows, on other platforms nothing) -/// /hello => <empty> +/// @code +/// //net/hello => //net +/// c:/hello => c: (on Windows, on other platforms nothing) +/// /hello => <empty> +/// @endcode /// /// @param path Input path. /// @result The root name of \a path if it has one, otherwise "". @@ -179,9 +190,11 @@ const StringRef root_name(StringRef path); /// @brief Get root directory. /// -/// /goo/hello => / -/// c:/hello => / -/// d/file.txt => <empty> +/// @code +/// /goo/hello => / +/// c:/hello => / +/// d/file.txt => <empty> +/// @endcode /// /// @param path Input path. /// @result The root directory of \a path if it has one, otherwise @@ -198,9 +211,11 @@ const StringRef root_path(StringRef path); /// @brief Get relative path. /// -/// C:\hello\world => hello\world -/// foo/bar => foo/bar -/// /foo/bar => foo/bar +/// @code +/// C:\hello\world => hello\world +/// foo/bar => foo/bar +/// /foo/bar => foo/bar +/// @endcode /// /// @param path Input path. /// @result The path starting after root_path if one exists, otherwise "". @@ -208,9 +223,11 @@ const StringRef relative_path(StringRef path); /// @brief Get parent path. /// -/// / => <empty> -/// /foo => / -/// foo/../bar => foo/.. +/// @code +/// / => <empty> +/// /foo => / +/// foo/../bar => foo/.. +/// @endcode /// /// @param path Input path. /// @result The parent path of \a path if one exists, otherwise "". @@ -218,10 +235,12 @@ const StringRef parent_path(StringRef path); /// @brief Get filename. /// -/// /foo.txt => foo.txt -/// . => . -/// .. => .. -/// / => / +/// @code +/// /foo.txt => foo.txt +/// . => . +/// .. => .. +/// / => / +/// @endcode /// /// @param path Input path. /// @result The filename part of \a path. This is defined as the last component @@ -234,11 +253,13 @@ const StringRef filename(StringRef path); /// substring of filename ending at (but not including) the last dot. Otherwise /// it is filename. /// -/// /foo/bar.txt => bar -/// /foo/bar => bar -/// /foo/.txt => <empty> -/// /foo/. => . -/// /foo/.. => .. +/// @code +/// /foo/bar.txt => bar +/// /foo/bar => bar +/// /foo/.txt => <empty> +/// /foo/. => . +/// /foo/.. => .. +/// @endcode /// /// @param path Input path. /// @result The stem of \a path. @@ -250,9 +271,11 @@ const StringRef stem(StringRef path); /// substring of filename starting at (and including) the last dot, and ending /// at the end of \a path. Otherwise "". /// -/// /foo/bar.txt => .txt -/// /foo/bar => <empty> -/// /foo/.txt => .txt +/// @code +/// /foo/bar.txt => .txt +/// /foo/bar => <empty> +/// /foo/.txt => .txt +/// @endcode /// /// @param path Input path. /// @result The extension of \a path. diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index 221fa8b..9fbe434 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -29,9 +29,11 @@ #ifndef LLVM_SUPPORT_PATTERNMATCH_H #define LLVM_SUPPORT_PATTERNMATCH_H -#include "llvm/Constants.h" -#include "llvm/Instructions.h" -#include "llvm/Operator.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Operator.h" +#include "llvm/Support/CallSite.h" namespace llvm { namespace PatternMatch { @@ -41,13 +43,13 @@ bool match(Val *V, const Pattern &P) { return const_cast<Pattern&>(P).match(V); } - + template<typename SubPattern_t> struct OneUse_match { SubPattern_t SubPattern; - + OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - + template<typename OpTy> bool match(OpTy *V) { return V->hasOneUse() && SubPattern.match(V); @@ -56,8 +58,8 @@ struct OneUse_match { template<typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) { return SubPattern; } - - + + template<typename Class> struct class_match { template<typename ITy> @@ -74,7 +76,53 @@ inline class_match<ConstantInt> m_ConstantInt() { inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); } inline class_match<Constant> m_Constant() { return class_match<Constant>(); } - + +/// Matching combinators +template<typename LTy, typename RTy> +struct match_combine_or { + LTy L; + RTy R; + + match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + + template<typename ITy> + bool match(ITy *V) { + if (L.match(V)) + return true; + if (R.match(V)) + return true; + return false; + } +}; + +template<typename LTy, typename RTy> +struct match_combine_and { + LTy L; + RTy R; + + match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + + template<typename ITy> + bool match(ITy *V) { + if (L.match(V)) + if (R.match(V)) + return true; + return false; + } +}; + +/// Combine two pattern matchers matching L || R +template<typename LTy, typename RTy> +inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) { + return match_combine_or<LTy, RTy>(L, R); +} + +/// Combine two pattern matchers matching L && R +template<typename LTy, typename RTy> +inline match_combine_and<LTy, RTy> m_CombineAnd(const LTy &L, const RTy &R) { + return match_combine_and<LTy, RTy>(L, R); +} + struct match_zero { template<typename ITy> bool match(ITy *V) { @@ -83,12 +131,33 @@ struct match_zero { return false; } }; - + /// m_Zero() - Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } - - + +struct match_neg_zero { + template<typename ITy> + bool match(ITy *V) { + if (const Constant *C = dyn_cast<Constant>(V)) + return C->isNegativeZeroValue(); + return false; + } +}; + +/// m_NegZero() - Match an arbitrary zero/null constant. This includes +/// zero_initializer for vectors and ConstantPointerNull for pointers. For +/// floating point constants, this will match negative zero but not positive +/// zero +inline match_neg_zero m_NegZero() { return match_neg_zero(); } + +/// m_AnyZero() - Match an arbitrary zero/null constant. This includes +/// zero_initializer for vectors and ConstantPointerNull for pointers. For +/// floating point constants, this will match negative zero and positive zero +inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() { + return m_CombineOr(m_Zero(), m_NegZero()); +} + struct apint_match { const APInt *&Res; apint_match(const APInt *&R) : Res(R) {} @@ -98,28 +167,22 @@ struct apint_match { Res = &CI->getValue(); return true; } - // FIXME: Remove this. - if (ConstantVector *CV = dyn_cast<ConstantVector>(V)) - if (ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) { - Res = &CI->getValue(); - return true; - } - if (ConstantDataVector *CV = dyn_cast<ConstantDataVector>(V)) - if (ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) { - Res = &CI->getValue(); - return true; - } + if (V->getType()->isVectorTy()) + if (const Constant *C = dyn_cast<Constant>(V)) + if (ConstantInt *CI = + dyn_cast_or_null<ConstantInt>(C->getSplatValue())) { + Res = &CI->getValue(); + return true; + } return false; } }; - + /// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } - + template<int64_t Val> struct constantint_match { template<typename ITy> @@ -151,17 +214,15 @@ struct cst_pred_ty : public Predicate { bool match(ITy *V) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) return this->isValue(CI->getValue()); - // FIXME: Remove this. - if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) - return this->isValue(CI->getValue()); - if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) - return this->isValue(CI->getValue()); + if (V->getType()->isVectorTy()) + if (const Constant *C = dyn_cast<Constant>(V)) + if (const ConstantInt *CI = + dyn_cast_or_null<ConstantInt>(C->getSplatValue())) + return this->isValue(CI->getValue()); return false; } }; - + /// api_pred_ty - This helper class is used to match scalar and vector constants /// that satisfy a specified predicate, and bind them to an APInt. template<typename Predicate> @@ -175,27 +236,19 @@ struct api_pred_ty : public Predicate { Res = &CI->getValue(); return true; } - - // FIXME: remove. - if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } - - if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } + if (V->getType()->isVectorTy()) + if (const Constant *C = dyn_cast<Constant>(V)) + if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } return false; } }; - - + + struct is_one { bool isValue(const APInt &C) { return C == 1; } }; @@ -203,11 +256,11 @@ struct is_one { /// m_One() - Match an integer 1 or a vector with all elements equal to 1. inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); } inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; } - + struct is_all_ones { bool isValue(const APInt &C) { return C.isAllOnesValue(); } }; - + /// m_AllOnes() - Match an integer or vector with all bits set to true. inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();} inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; } @@ -252,6 +305,9 @@ inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; } /// m_Constant - Match a Constant, capturing the value if we match. inline bind_ty<Constant> m_Constant(Constant *&C) { return C; } +/// m_ConstantFP - Match a ConstantFP, capturing the value if we match. +inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; } + /// specificval_ty - Match a specified Value*. struct specificval_ty { const Value *Val; @@ -266,10 +322,35 @@ struct specificval_ty { /// m_Specific - Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } +/// Match a specified floating point value or vector of all elements of that +/// value. +struct specific_fpval { + double Val; + specific_fpval(double V) : Val(V) {} + + template<typename ITy> + bool match(ITy *V) { + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V)) + return CFP->isExactlyValue(Val); + if (V->getType()->isVectorTy()) + if (const Constant *C = dyn_cast<Constant>(V)) + if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue())) + return CFP->isExactlyValue(Val); + return false; + } +}; + +/// Match a specific floating point value or vector with all elements equal to +/// the value. +inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } + +/// Match a float 1.0 or vector with all elements equal to 1.0. +inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } + struct bind_const_intval_ty { uint64_t &VR; bind_const_intval_ty(uint64_t &V) : VR(V) {} - + template<typename ITy> bool match(ITy *V) { if (ConstantInt *CV = dyn_cast<ConstantInt>(V)) @@ -284,7 +365,7 @@ struct bind_const_intval_ty { /// m_ConstantInt - Match a ConstantInt and bind to its value. This does not /// match ConstantInts wider than 64-bits. inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } - + //===----------------------------------------------------------------------===// // Matchers for specific binary operators. // @@ -583,7 +664,7 @@ inline CastClass_match<OpTy, Instruction::BitCast> m_BitCast(const OpTy &Op) { return CastClass_match<OpTy, Instruction::BitCast>(Op); } - + /// m_PtrToInt template<typename OpTy> inline CastClass_match<OpTy, Instruction::PtrToInt> @@ -611,7 +692,7 @@ inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::ZExt>(Op); } - + //===----------------------------------------------------------------------===// // Matchers for unary operators @@ -700,6 +781,25 @@ inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; } // Matchers for control flow. // +struct br_match { + BasicBlock *&Succ; + br_match(BasicBlock *&Succ) + : Succ(Succ) { + } + + template<typename OpTy> + bool match(OpTy *V) { + if (BranchInst *BI = dyn_cast<BranchInst>(V)) + if (BI->isUnconditional()) { + Succ = BI->getSuccessor(0); + return true; + } + return false; + } +}; + +inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } + template<typename Cond_t> struct brc_match { Cond_t Cond; @@ -818,6 +918,102 @@ m_UMin(const LHS &L, const RHS &R) { return MaxMin_match<LHS, RHS, umin_pred_ty>(L, R); } +template<typename Opnd_t> +struct Argument_match { + unsigned OpI; + Opnd_t Val; + Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { } + + template<typename OpTy> + bool match(OpTy *V) { + CallSite CS(V); + return CS.isCall() && Val.match(CS.getArgument(OpI)); + } +}; + +/// Match an argument +template<unsigned OpI, typename Opnd_t> +inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) { + return Argument_match<Opnd_t>(OpI, Op); +} + +/// Intrinsic matchers. +struct IntrinsicID_match { + unsigned ID; + IntrinsicID_match(unsigned IntrID) : ID(IntrID) { } + + template<typename OpTy> + bool match(OpTy *V) { + IntrinsicInst *II = dyn_cast<IntrinsicInst>(V); + return II && II->getIntrinsicID() == ID; + } +}; + +/// Intrinsic matches are combinations of ID matchers, and argument +/// matchers. Higher arity matcher are defined recursively in terms of and-ing +/// them with lower arity matchers. Here's some convenient typedefs for up to +/// several arguments, and more can be added as needed +template <typename T0 = void, typename T1 = void, typename T2 = void, + typename T3 = void, typename T4 = void, typename T5 = void, + typename T6 = void, typename T7 = void, typename T8 = void, + typename T9 = void, typename T10 = void> struct m_Intrinsic_Ty; +template <typename T0> +struct m_Intrinsic_Ty<T0> { + typedef match_combine_and<IntrinsicID_match, Argument_match<T0> > Ty; +}; +template <typename T0, typename T1> +struct m_Intrinsic_Ty<T0, T1> { + typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty, + Argument_match<T1> > Ty; +}; +template <typename T0, typename T1, typename T2> +struct m_Intrinsic_Ty<T0, T1, T2> { + typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1>::Ty, + Argument_match<T2> > Ty; +}; +template <typename T0, typename T1, typename T2, typename T3> +struct m_Intrinsic_Ty<T0, T1, T2, T3> { + typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1, T2>::Ty, + Argument_match<T3> > Ty; +}; + +/// Match intrinsic calls like this: +/// m_Intrinsic<Intrinsic::fabs>(m_Value(X)) +template <unsigned IntrID> +inline IntrinsicID_match +m_Intrinsic() { return IntrinsicID_match(IntrID); } + +template<unsigned 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> +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> +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> +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)); +} + +// Helper intrinsic matching specializations +template<typename Opnd0> +inline typename m_Intrinsic_Ty<Opnd0>::Ty +m_BSwap(const Opnd0 &Op0) { + return m_Intrinsic<Intrinsic::bswap>(Op0); +} + } // end namespace PatternMatch } // end namespace llvm diff --git a/include/llvm/Support/PredIteratorCache.h b/include/llvm/Support/PredIteratorCache.h index bb66a8e..c5fb780 100644 --- a/include/llvm/Support/PredIteratorCache.h +++ b/include/llvm/Support/PredIteratorCache.h @@ -11,10 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/Allocator.h" -#include "llvm/Support/CFG.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/CFG.h" #ifndef LLVM_SUPPORT_PREDITERATORCACHE_H #define LLVM_SUPPORT_PREDITERATORCACHE_H diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h index 9b3ecda..2122e06 100644 --- a/include/llvm/Support/PrettyStackTrace.h +++ b/include/llvm/Support/PrettyStackTrace.h @@ -16,6 +16,8 @@ #ifndef LLVM_SUPPORT_PRETTYSTACKTRACE_H #define LLVM_SUPPORT_PRETTYSTACKTRACE_H +#include "llvm/Support/Compiler.h" + namespace llvm { class raw_ostream; @@ -32,8 +34,8 @@ namespace llvm { /// virtual stack trace. This gets dumped out if the program crashes. class PrettyStackTraceEntry { const PrettyStackTraceEntry *NextEntry; - PrettyStackTraceEntry(const PrettyStackTraceEntry &); // DO NOT IMPLEMENT - void operator=(const PrettyStackTraceEntry&); // DO NOT IMPLEMENT + PrettyStackTraceEntry(const PrettyStackTraceEntry &) LLVM_DELETED_FUNCTION; + void operator=(const PrettyStackTraceEntry&) LLVM_DELETED_FUNCTION; public: PrettyStackTraceEntry(); virtual ~PrettyStackTraceEntry(); @@ -52,7 +54,7 @@ namespace llvm { const char *Str; public: PrettyStackTraceString(const char *str) : Str(str) {} - virtual void print(raw_ostream &OS) const; + virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; }; /// PrettyStackTraceProgram - This object prints a specified program arguments @@ -63,7 +65,7 @@ namespace llvm { public: PrettyStackTraceProgram(int argc, const char * const*argv) : ArgC(argc), ArgV(argv) {} - virtual void print(raw_ostream &OS) const; + virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; }; } // end namespace llvm diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index 088897c..ea8da6d 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -6,152 +6,246 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file declares the llvm::sys::Process class. -// +/// \file +/// +/// Provides a library for accessing information about this process and other +/// processes on the operating system. Also provides means of spawning +/// subprocess for commands. The design of this library is modeled after the +/// proposed design of the Boost.Process library, and is design specifically to +/// follow the style of standard libraries and potentially become a proposal +/// for a standard library. +/// +/// This file declares the llvm::sys::Process class which contains a collection +/// of legacy static interfaces for extracting various information about the +/// current process. The goal is to migrate users of this API over to the new +/// interfaces. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_SYSTEM_PROCESS_H #define LLVM_SYSTEM_PROCESS_H +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/TimeValue.h" namespace llvm { namespace sys { - /// This class provides an abstraction for getting information about the - /// currently executing process. - /// @since 1.4 - /// @brief An abstraction for operating system processes. - class Process { - /// @name Accessors - /// @{ - public: - /// This static function will return the operating system's virtual memory - /// page size. - /// @returns The number of bytes in a virtual memory page. - /// @brief Get the virtual memory page size - static unsigned GetPageSize(); - - /// This static function will return the total amount of memory allocated - /// by the process. This only counts the memory allocated via the malloc, - /// calloc and realloc functions and includes any "free" holes in the - /// allocated space. - /// @brief Return process memory usage. - static size_t GetMallocUsage(); - - /// This static function will return the total memory usage of the - /// process. This includes code, data, stack and mapped pages usage. Notei - /// that the value returned here is not necessarily the Running Set Size, - /// it is the total virtual memory usage, regardless of mapped state of - /// that memory. - static size_t GetTotalMemoryUsage(); - - /// This static function will set \p user_time to the amount of CPU time - /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU - /// time spent in system (kernel) mode. If the operating system does not - /// support collection of these metrics, a zero TimeValue will be for both - /// values. - static void GetTimeUsage( - TimeValue& elapsed, - ///< Returns the TimeValue::now() giving current time - TimeValue& user_time, - ///< Returns the current amount of user time for the process - TimeValue& sys_time - ///< Returns the current amount of system time for the process - ); - - /// 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 determines if the standard input is connected directly - /// to a user's input (keyboard probably), rather than coming from a file - /// or pipe. - static bool StandardInIsUserInput(); - - /// This function determines if the standard output is connected to a - /// "tty" or "console" window. That is, the output would be displayed to - /// the user rather than being put on a pipe or stored in a file. - static bool StandardOutIsDisplayed(); - - /// This function determines if the standard error is connected to a - /// "tty" or "console" window. That is, the output would be displayed to - /// the user rather than being put on a pipe or stored in a file. - static bool StandardErrIsDisplayed(); - - /// This function determines if the given file descriptor is connected to - /// a "tty" or "console" window. That is, the output would be displayed to - /// the user rather than being put on a pipe or stored in a file. - static bool FileDescriptorIsDisplayed(int fd); - - /// This function determines if the given file descriptor is displayd and - /// supports colors. - static bool FileDescriptorHasColors(int fd); - - /// This function determines the number of columns in the window - /// if standard output is connected to a "tty" or "console" - /// window. If standard output is not connected to a tty or - /// console, or if the number of columns cannot be determined, - /// this routine returns zero. - static unsigned StandardOutColumns(); - - /// This function determines the number of columns in the window - /// if standard error is connected to a "tty" or "console" - /// window. If standard error is not connected to a tty or - /// console, or if the number of columns cannot be determined, - /// this routine returns zero. - static unsigned StandardErrColumns(); - - /// This function determines whether the terminal connected to standard - /// output supports colors. If standard output is not connected to a - /// terminal, this function returns false. - static bool StandardOutHasColors(); - - /// This function determines whether the terminal connected to standard - /// error supports colors. If standard error is not connected to a - /// terminal, this function returns false. - static bool StandardErrHasColors(); - - /// Whether changing colors requires the output to be flushed. - /// This is needed on systems that don't support escape sequences for - /// changing colors. - static bool ColorNeedsFlush(); - - /// This function returns the colorcode escape sequences. - /// If ColorNeedsFlush() is true then this function will change the colors - /// and return an empty escape sequence. In that case it is the - /// responsibility of the client to flush the output stream prior to - /// calling this function. - static const char *OutputColor(char c, bool bold, bool bg); - - /// Same as OutputColor, but only enables the bold attribute. - static const char *OutputBold(bool bg); - - /// This function returns the escape sequence to reverse forground and - /// background colors. - static const char *OutputReverse(); - - /// Resets the terminals colors, or returns an escape sequence to do so. - static const char *ResetColor(); - - /// Get the result of a process wide random number generator. The - /// generator will be automatically seeded in non-deterministic fashion. - static unsigned GetRandomNumber(); - /// @} - }; +class self_process; + +/// \brief Generic base class which exposes information about an operating +/// system process. +/// +/// This base class is the core interface behind any OS process. It exposes +/// methods to query for generic information about a particular process. +/// +/// Subclasses implement this interface based on the mechanisms available, and +/// can optionally expose more interfaces unique to certain process kinds. +class process { +protected: + /// \brief Only specific subclasses of process objects can be destroyed. + virtual ~process(); + +public: + /// \brief Operating system specific type to identify a process. + /// + /// Note that the windows one is defined to 'void *' as this is the + /// documented type for HANDLE on windows, and we don't want to pull in the + /// Windows headers here. +#if defined(LLVM_ON_UNIX) + typedef pid_t id_type; +#elif defined(LLVM_ON_WIN32) + typedef void *id_type; // Must match the type of HANDLE. +#else +#error Unsupported operating system. +#endif + + /// \brief Get the operating system specific identifier for this process. + virtual id_type get_id() = 0; + + /// \brief Get the user time consumed by this process. + /// + /// Note that this is often an approximation and may be zero on platforms + /// where we don't have good support for the functionality. + virtual TimeValue get_user_time() const = 0; + + /// \brief Get the system time consumed by this process. + /// + /// Note that this is often an approximation and may be zero on platforms + /// where we don't have good support for the functionality. + virtual TimeValue get_system_time() const = 0; + + /// \brief Get the wall time consumed by this process. + /// + /// Note that this is often an approximation and may be zero on platforms + /// where we don't have good support for the functionality. + virtual TimeValue get_wall_time() const = 0; + + /// \name Static factory routines for processes. + /// @{ + + /// \brief Get the process object for the current process. + static self_process *get_self(); + + /// @} + +}; + +/// \brief The specific class representing the current process. +/// +/// The current process can both specialize the implementation of the routines +/// and can expose certain information not available for other OS processes. +class self_process : public process { + friend class process; + + /// \brief Private destructor, as users shouldn't create objects of this + /// type. + virtual ~self_process(); + +public: + virtual id_type get_id(); + virtual TimeValue get_user_time() const; + virtual TimeValue get_system_time() const; + virtual TimeValue get_wall_time() const; + + /// \name Process configuration (sysconf on POSIX) + /// @{ + + /// \brief Get the virtual memory page size. + /// + /// Query the operating system for this process's page size. + size_t page_size() const { return PageSize; }; + + /// @} + +private: + /// \name Cached process state. + /// @{ + + /// \brief Cached page size, this cannot vary during the life of the process. + size_t PageSize; + + /// @} + + /// \brief Constructor, used by \c process::get_self() only. + self_process(); +}; + + +/// \brief A collection of legacy interfaces for querying information about the +/// current executing process. +class Process { +public: + /// \brief Return process memory usage. + /// This static function will return the total amount of memory allocated + /// by the process. This only counts the memory allocated via the malloc, + /// calloc and realloc functions and includes any "free" holes in the + /// allocated space. + static size_t GetMallocUsage(); + + /// This static function will set \p user_time to the amount of CPU time + /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU + /// time spent in system (kernel) mode. If the operating system does not + /// support collection of these metrics, a zero TimeValue will be for both + /// values. + /// \param elapsed Returns the TimeValue::now() giving current time + /// \param user_time Returns the current amount of user time for the process + /// \param sys_time Returns the current amount of system time for the process + 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 determines if the standard input is connected directly + /// to a user's input (keyboard probably), rather than coming from a file + /// or pipe. + static bool StandardInIsUserInput(); + + /// This function determines if the standard output is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardOutIsDisplayed(); + + /// This function determines if the standard error is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardErrIsDisplayed(); + + /// This function determines if the given file descriptor is connected to + /// a "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool FileDescriptorIsDisplayed(int fd); + + /// This function determines if the given file descriptor is displayd and + /// supports colors. + static bool FileDescriptorHasColors(int fd); + + /// This function determines the number of columns in the window + /// if standard output is connected to a "tty" or "console" + /// window. If standard output is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardOutColumns(); + + /// This function determines the number of columns in the window + /// if standard error is connected to a "tty" or "console" + /// window. If standard error is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardErrColumns(); + + /// This function determines whether the terminal connected to standard + /// output supports colors. If standard output is not connected to a + /// terminal, this function returns false. + static bool StandardOutHasColors(); + + /// This function determines whether the terminal connected to standard + /// error supports colors. If standard error is not connected to a + /// terminal, this function returns false. + static bool StandardErrHasColors(); + + /// Whether changing colors requires the output to be flushed. + /// This is needed on systems that don't support escape sequences for + /// changing colors. + static bool ColorNeedsFlush(); + + /// This function returns the colorcode escape sequences. + /// If ColorNeedsFlush() is true then this function will change the colors + /// and return an empty escape sequence. In that case it is the + /// responsibility of the client to flush the output stream prior to + /// calling this function. + static const char *OutputColor(char c, bool bold, bool bg); + + /// Same as OutputColor, but only enables the bold attribute. + static const char *OutputBold(bool bg); + + /// This function returns the escape sequence to reverse forground and + /// background colors. + static const char *OutputReverse(); + + /// Resets the terminals colors, or returns an escape sequence to do so. + static const char *ResetColor(); + + /// Get the result of a process wide random number generator. The + /// generator will be automatically seeded in non-deterministic fashion. + static unsigned GetRandomNumber(); +}; + } } diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index a85f235..028565d 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -34,19 +34,15 @@ namespace sys { void *Data_; // Noncopyable. - Program(const Program& other); - Program& operator=(const Program& other); + Program(const Program& other) LLVM_DELETED_FUNCTION; + Program& operator=(const Program& other) LLVM_DELETED_FUNCTION; /// @name Methods /// @{ - public: Program(); ~Program(); - /// Return process ID of this program. - unsigned GetPid() const; - /// This function executes the program using the \p arguments provided. The /// invoked program will inherit the stdin, stdout, and stderr file /// descriptors, the environment and other configuration settings of the @@ -103,17 +99,7 @@ namespace sys { ///< is non-empty upon return an error occurred while waiting. ); - /// This function terminates the program. - /// @returns true if an error occurred. - /// @see Execute - /// @brief Terminates the program. - bool Kill - ( 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 killing the - ///< program. - ); - + public: /// 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 diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h index 0d4cb81..935b307 100644 --- a/include/llvm/Support/RWMutex.h +++ b/include/llvm/Support/RWMutex.h @@ -14,6 +14,7 @@ #ifndef LLVM_SYSTEM_RWMUTEX_H #define LLVM_SYSTEM_RWMUTEX_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/Threading.h" #include <cassert> @@ -75,8 +76,8 @@ namespace llvm /// @name Do Not Implement /// @{ private: - RWMutexImpl(const RWMutexImpl & original); - void operator=(const RWMutexImpl &); + RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION; + void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION; /// @} }; diff --git a/include/llvm/Support/Recycler.h b/include/llvm/Support/Recycler.h index fa6e189..bcc561d 100644 --- a/include/llvm/Support/Recycler.h +++ b/include/llvm/Support/Recycler.h @@ -22,6 +22,8 @@ namespace llvm { +class BumpPtrAllocator; + /// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for /// printing statistics. /// @@ -87,6 +89,15 @@ public: } } + /// Special case for BumpPtrAllocator which has an empty Deallocate() + /// function. + /// + /// There is no need to traverse the free list, pulling all the objects into + /// cache. + void clear(BumpPtrAllocator&) { + FreeList.clearAndLeakNodesUnsafely(); + } + template<class SubClass, class AllocatorType> SubClass *Allocate(AllocatorType &Allocator) { assert(sizeof(SubClass) <= Size && diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h index 7648e77..82df2c6 100644 --- a/include/llvm/Support/Regex.h +++ b/include/llvm/Support/Regex.h @@ -7,7 +7,10 @@ // //===----------------------------------------------------------------------===// // -// This file implements a POSIX regular expression matcher. +// This file implements a POSIX regular expression matcher. Both Basic and +// Extended POSIX regular expressions (ERE) are supported. EREs were extended +// to support backreferences in matches. +// This implementation also supports matching strings with embedded NUL chars. // //===----------------------------------------------------------------------===// @@ -33,12 +36,14 @@ namespace llvm { /// null string after any newline in the string in addition to its normal /// function, and the $ anchor matches the null string before any /// newline in the string in addition to its normal function. - Newline=2 + Newline=2, + /// By default, the POSIX extended regular expression (ERE) syntax is + /// assumed. Pass this flag to turn on basic regular expressions (BRE) + /// instead. + BasicRegex=4 }; - /// Compiles the given POSIX Extended Regular Expression \arg Regex. - /// This implementation supports regexes and matching strings with embedded - /// NUL characters. + /// Compiles the given regular expression \p Regex. Regex(StringRef Regex, unsigned Flags = NoFlags); ~Regex(); @@ -51,17 +56,17 @@ namespace llvm { /// many entries plus one for the whole regex (as element 0). unsigned getNumMatches() const; - /// matches - Match the regex against a given \arg String. + /// matches - Match the regex against a given \p String. /// /// \param Matches - If given, on a successful match this will be filled in - /// with references to the matched group expressions (inside \arg String), + /// with references to the matched group expressions (inside \p String), /// the first group is always the entire pattern. /// /// This returns true on a successful match. bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = 0); /// sub - Return the result of replacing the first match of the regex in - /// \arg String with the \arg Repl string. Backreferences like "\0" in the + /// \p String with the \p Repl string. Backreferences like "\0" in the /// replacement string are replaced with the appropriate match substring. /// /// Note that the replacement string has backslash escaping performed on diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h index d0375be..29eafb6 100644 --- a/include/llvm/Support/Registry.h +++ b/include/llvm/Support/Registry.h @@ -37,7 +37,7 @@ namespace llvm { /// is necessary to define an alternate traits class. template <typename T> class RegistryTraits { - RegistryTraits(); // Do not implement. + RegistryTraits() LLVM_DELETED_FUNCTION; public: typedef SimpleRegistryEntry<T> entry; @@ -63,7 +63,7 @@ namespace llvm { class iterator; private: - Registry(); // Do not implement. + Registry() LLVM_DELETED_FUNCTION; static void Announce(const entry &E) { for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) @@ -120,6 +120,7 @@ namespace llvm { /// Abstract base class for registry listeners, which are informed when new /// entries are added to the registry. Simply subclass and instantiate: /// + /// \code /// class CollectorPrinter : public Registry<Collector>::listener { /// protected: /// void registered(const Registry<Collector>::entry &e) { @@ -131,7 +132,7 @@ namespace llvm { /// }; /// /// CollectorPrinter Printer; - /// + /// \endcode class listener { listener *Prev, *Next; diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h index 1bf810b..2b0e9df 100644 --- a/include/llvm/Support/SMLoc.h +++ b/include/llvm/Support/SMLoc.h @@ -19,7 +19,7 @@ namespace llvm { -/// SMLoc - Represents a location in source code. +/// Represents a location in source code. class SMLoc { const char *Ptr; public: @@ -39,9 +39,11 @@ public: } }; -/// SMRange - Represents a range in source code. Note that unlike standard STL -/// ranges, the locations specified are considered to be *inclusive*. For -/// example, [X,X] *does* include X, it isn't an empty range. +/// Represents a range in source code. +/// +/// SMRange is implemented using a half-open range, as is the convention in C++. +/// In the string "abc", the range (1,3] represents the substring "bc", and the +/// range (2,2] represents an empty range between the characters "b" and "c". class SMRange { public: SMLoc Start, End; diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 3835e84..aaee344 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -16,8 +16,8 @@ #ifndef SUPPORT_SOURCEMGR_H #define SUPPORT_SOURCEMGR_H -#include "llvm/Support/SMLoc.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/SMLoc.h" #include <string> namespace llvm { @@ -64,9 +64,9 @@ private: DiagHandlerTy DiagHandler; void *DiagContext; - - SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT - void operator=(const SourceMgr&); // DO NOT IMPLEMENT + + SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION; + void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION; public: SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {} ~SourceMgr(); @@ -95,6 +95,10 @@ public: return Buffers[i].Buffer; } + unsigned getNumBuffers() const { + return Buffers.size(); + } + SMLoc getParentIncludeLoc(unsigned i) const { assert(i < Buffers.size() && "Invalid Buffer ID!"); return Buffers[i].IncludeLoc; diff --git a/include/llvm/Support/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h index 531dbb2..2e1163f 100644 --- a/include/llvm/Support/StreamableMemoryObject.h +++ b/include/llvm/Support/StreamableMemoryObject.h @@ -12,8 +12,9 @@ #define STREAMABLEMEMORYOBJECT_H_ #include "llvm/ADT/OwningPtr.h" -#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataStream.h" +#include "llvm/Support/MemoryObject.h" #include <vector> namespace llvm { @@ -107,14 +108,15 @@ class StreamableMemoryObject : public MemoryObject { class StreamingMemoryObject : public StreamableMemoryObject { public: StreamingMemoryObject(DataStreamer *streamer); - virtual uint64_t getBase() const { return 0; } - virtual uint64_t getExtent() const; - virtual int readByte(uint64_t address, uint8_t* ptr) const; + virtual uint64_t getBase() const LLVM_OVERRIDE { return 0; } + virtual uint64_t getExtent() const LLVM_OVERRIDE; + virtual int readByte(uint64_t address, uint8_t* ptr) const LLVM_OVERRIDE; virtual int readBytes(uint64_t address, uint64_t size, uint8_t* buf, - uint64_t* copied) const ; - virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const { + uint64_t* copied) const LLVM_OVERRIDE; + virtual const uint8_t *getPointer(uint64_t address, + uint64_t size) const LLVM_OVERRIDE { // This could be fixed by ensuring the bytes are fetched and making a copy, // requiring that the bitcode size be known, or otherwise ensuring that // the memory doesn't go away/get reallocated, but it's @@ -122,8 +124,8 @@ public: assert(0 && "getPointer in streaming memory objects not allowed"); return NULL; } - virtual bool isValidAddress(uint64_t address) const; - virtual bool isObjectEnd(uint64_t address) const; + virtual bool isValidAddress(uint64_t address) const LLVM_OVERRIDE; + virtual bool isObjectEnd(uint64_t address) const LLVM_OVERRIDE; /// Drop s bytes from the front of the stream, pushing the positions of the /// remaining bytes down by s. This is used to skip past the bitcode header, @@ -170,8 +172,8 @@ private: return true; } - StreamingMemoryObject(const StreamingMemoryObject&); // DO NOT IMPLEMENT - void operator=(const StreamingMemoryObject&); // DO NOT IMPLEMENT + StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; + void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; }; StreamableMemoryObject *getNonStreamedMemoryObject( diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index de05e0b..71adbc5 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -30,8 +30,8 @@ #define LLVM_SUPPORT_STRINGPOOL_H #include "llvm/ADT/StringMap.h" -#include <new> #include <cassert> +#include <new> namespace llvm { diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Support/TargetFolder.h index c65faa6..5c1978d 100644 --- a/include/llvm/Support/TargetFolder.h +++ b/include/llvm/Support/TargetFolder.h @@ -19,18 +19,18 @@ #ifndef LLVM_SUPPORT_TARGETFOLDER_H #define LLVM_SUPPORT_TARGETFOLDER_H -#include "llvm/Constants.h" -#include "llvm/InstrTypes.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Analysis/ConstantFolding.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/InstrTypes.h" namespace llvm { -class TargetData; +class DataLayout; /// TargetFolder - Create constants with target dependent folding. class TargetFolder { - const TargetData *TD; + const DataLayout *TD; /// Fold - Fold the constant using target specific information. Constant *Fold(Constant *C) const { @@ -41,7 +41,7 @@ class TargetFolder { } public: - explicit TargetFolder(const TargetData *TheTD) : TD(TheTD) {} + explicit TargetFolder(const DataLayout *TheTD) : TD(TheTD) {} //===--------------------------------------------------------------------===// // Binary Operators @@ -177,7 +177,14 @@ public: return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); } Constant *CreatePointerCast(Constant *C, Type *DestTy) const { - return ConstantExpr::getPointerCast(C, DestTy); + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getPointerCast(C, DestTy)); + } + Constant *CreateFPCast(Constant *C, Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getFPCast(C, DestTy)); } Constant *CreateBitCast(Constant *C, Type *DestTy) const { return CreateCast(Instruction::BitCast, C, DestTy); diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index c0be8f1..b06676d 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -19,10 +19,10 @@ #ifndef LLVM_SUPPORT_TARGETREGISTRY_H #define LLVM_SUPPORT_TARGETREGISTRY_H -#include "llvm/Support/CodeGen.h" #include "llvm/ADT/Triple.h" -#include <string> +#include "llvm/Support/CodeGen.h" #include <cassert> +#include <string> namespace llvm { class AsmPrinter; @@ -41,7 +41,6 @@ namespace llvm { class MCRegisterInfo; class MCStreamer; class MCSubtargetInfo; - class MCTargetAsmLexer; class MCTargetAsmParser; class TargetMachine; class TargetOptions; @@ -93,10 +92,9 @@ namespace llvm { CodeGenOpt::Level OL); typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, MCStreamer &Streamer); - typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, StringRef TT); - typedef MCTargetAsmLexer *(*MCAsmLexerCtorTy)(const Target &T, - const MCRegisterInfo &MRI, - const MCAsmInfo &MAI); + typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, + StringRef TT, + StringRef CPU); typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(MCSubtargetInfo &STI, MCAsmParser &P); typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, @@ -180,10 +178,6 @@ namespace llvm { /// MCAsmBackend, if registered. MCAsmBackendCtorTy MCAsmBackendCtorFn; - /// MCAsmLexerCtorFn - Construction function for this target's - /// MCTargetAsmLexer, if registered. - MCAsmLexerCtorTy MCAsmLexerCtorFn; - /// MCAsmParserCtorFn - Construction function for this target's /// MCTargetAsmParser, if registered. MCAsmParserCtorTy MCAsmParserCtorFn; @@ -240,9 +234,6 @@ namespace llvm { /// hasMCAsmBackend - Check if this target supports .o generation. bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != 0; } - /// hasMCAsmLexer - Check if this target supports .s lexing. - bool hasMCAsmLexer() const { return MCAsmLexerCtorFn != 0; } - /// hasAsmParser - Check if this target supports .s parsing. bool hasMCAsmParser() const { return MCAsmParserCtorFn != 0; } @@ -271,7 +262,7 @@ namespace llvm { /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified /// target triple. /// - /// \arg Triple - This argument is used to determine the target machine + /// \param Triple This argument is used to determine the target machine /// feature set; it should always be provided. Generally this should be /// either the target triple from the module, or the target triple of the /// host if that does not exist. @@ -317,12 +308,12 @@ namespace llvm { /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation. /// - /// \arg Triple - This argument is used to determine the target machine + /// \param Triple This argument is used to determine the target machine /// feature set; it should always be provided. Generally this should be /// either the target triple from the module, or the target triple of the /// host if that does not exist. - /// \arg CPU - This specifies the name of the target CPU. - /// \arg Features - This specifies the string representation of the + /// \param CPU This specifies the name of the target CPU. + /// \param Features This specifies the string representation of the /// additional target features. MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU, StringRef Features) const { @@ -332,9 +323,9 @@ namespace llvm { } /// createTargetMachine - Create a target specific machine implementation - /// for the specified \arg Triple. + /// for the specified \p Triple. /// - /// \arg Triple - This argument is used to determine the target machine + /// \param Triple This argument is used to determine the target machine /// feature set; it should always be provided. Generally this should be /// either the target triple from the module, or the target triple of the /// host if that does not exist. @@ -351,26 +342,16 @@ namespace llvm { /// createMCAsmBackend - Create a target specific assembly parser. /// - /// \arg Triple - The target triple string. - /// \arg Backend - The target independent assembler object. - MCAsmBackend *createMCAsmBackend(StringRef Triple) const { + /// \param Triple The target triple string. + MCAsmBackend *createMCAsmBackend(StringRef Triple, StringRef CPU) const { if (!MCAsmBackendCtorFn) return 0; - return MCAsmBackendCtorFn(*this, Triple); - } - - /// createMCAsmLexer - Create a target specific assembly lexer. - /// - MCTargetAsmLexer *createMCAsmLexer(const MCRegisterInfo &MRI, - const MCAsmInfo &MAI) const { - if (!MCAsmLexerCtorFn) - return 0; - return MCAsmLexerCtorFn(*this, MRI, MAI); + return MCAsmBackendCtorFn(*this, Triple, CPU); } /// createMCAsmParser - Create a target specific assembly parser. /// - /// \arg Parser - The target independent parser implementation to use for + /// \param Parser The target independent parser implementation to use for /// parsing and lexing. MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI, MCAsmParser &Parser) const { @@ -416,13 +397,13 @@ namespace llvm { /// createMCObjectStreamer - Create a target specific MCStreamer. /// - /// \arg TT - The target triple. - /// \arg Ctx - The target context. - /// \arg TAB - The target assembler backend object. Takes ownership. - /// \arg _OS - The stream object. - /// \arg _Emitter - The target independent assembler object.Takes ownership. - /// \arg RelaxAll - Relax all fixups? - /// \arg NoExecStack - Mark file as not needing a executable stack. + /// \param TT The target triple. + /// \param Ctx The target context. + /// \param TAB The target assembler backend object. Takes ownership. + /// \param _OS The stream object. + /// \param _Emitter The target independent assembler object.Takes ownership. + /// \param RelaxAll Relax all fixups? + /// \param NoExecStack Mark file as not needing a executable stack. MCStreamer *createMCObjectStreamer(StringRef TT, MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &_OS, @@ -675,20 +656,6 @@ namespace llvm { T.MCAsmBackendCtorFn = Fn; } - /// RegisterMCAsmLexer - Register a MCTargetAsmLexer implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCAsmLexer for the target. - static void RegisterMCAsmLexer(Target &T, Target::MCAsmLexerCtorTy Fn) { - if (!T.MCAsmLexerCtorFn) - T.MCAsmLexerCtorFn = Fn; - } - /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for /// the given target. /// @@ -1063,30 +1030,9 @@ namespace llvm { } private: - static MCAsmBackend *Allocator(const Target &T, StringRef Triple) { - return new MCAsmBackendImpl(T, Triple); - } - }; - - /// RegisterMCAsmLexer - Helper template for registering a target specific - /// assembly lexer, for use in the target machine initialization - /// function. Usage: - /// - /// extern "C" void LLVMInitializeFooMCAsmLexer() { - /// extern Target TheFooTarget; - /// RegisterMCAsmLexer<FooMCAsmLexer> X(TheFooTarget); - /// } - template<class MCAsmLexerImpl> - struct RegisterMCAsmLexer { - RegisterMCAsmLexer(Target &T) { - TargetRegistry::RegisterMCAsmLexer(T, &Allocator); - } - - private: - static MCTargetAsmLexer *Allocator(const Target &T, - const MCRegisterInfo &MRI, - const MCAsmInfo &MAI) { - return new MCAsmLexerImpl(T, MRI, MAI); + static MCAsmBackend *Allocator(const Target &T, StringRef Triple, + StringRef CPU) { + return new MCAsmBackendImpl(T, Triple, CPU); } }; diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h index 62ec90a..01f735c 100644 --- a/include/llvm/Support/ThreadLocal.h +++ b/include/llvm/Support/ThreadLocal.h @@ -14,8 +14,8 @@ #ifndef LLVM_SYSTEM_THREAD_LOCAL_H #define LLVM_SYSTEM_THREAD_LOCAL_H -#include "llvm/Support/Threading.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Threading.h" #include <cassert> namespace llvm { diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index c0e842c..9017afb 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -41,8 +41,8 @@ namespace llvm { /// before llvm_start_multithreaded(). void llvm_release_global_lock(); - /// llvm_execute_on_thread - Execute the given \arg UserFn on a separate - /// thread, passing it the provided \arg UserData. + /// llvm_execute_on_thread - Execute the given \p UserFn on a separate + /// thread, passing it the provided \p UserData. /// /// This function does not guarantee that the code will actually be executed /// on a separate thread or honoring the requested stack size, but tries to do diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h index e780b50..ab7401a 100644 --- a/include/llvm/Support/TimeValue.h +++ b/include/llvm/Support/TimeValue.h @@ -11,12 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/DataTypes.h" -#include <string> - #ifndef LLVM_SYSTEM_TIMEVALUE_H #define LLVM_SYSTEM_TIMEVALUE_H +#include "llvm/Support/DataTypes.h" +#include <string> + namespace llvm { namespace sys { /// This class is used where a precise fixed point in time is required. The @@ -82,6 +82,9 @@ namespace sys { /// @name Constructors /// @{ public: + /// \brief Default construct a time value, initializing to ZeroTime. + TimeValue() : seconds_(0), nanos_(0) {} + /// Caller provides the exact value in seconds and nanoseconds. The /// \p nanos argument defaults to zero for convenience. /// @brief Explicit constructor diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index 404cb6d..789c05f 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -15,12 +15,13 @@ #ifndef LLVM_SUPPORT_TIMER_H #define LLVM_SUPPORT_TIMER_H -#include "llvm/Support/DataTypes.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <string> -#include <vector> #include <utility> +#include <vector> namespace llvm { @@ -130,7 +131,7 @@ private: /// class TimeRegion { Timer *T; - TimeRegion(const TimeRegion &); // DO NOT IMPLEMENT + TimeRegion(const TimeRegion &) LLVM_DELETED_FUNCTION; public: explicit TimeRegion(Timer &t) : T(&t) { T->startTimer(); @@ -168,8 +169,8 @@ class TimerGroup { std::vector<std::pair<TimeRecord, std::string> > TimersToPrint; TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's. - TimerGroup(const TimerGroup &TG); // DO NOT IMPLEMENT - void operator=(const TimerGroup &TG); // DO NOT IMPLEMENT + TimerGroup(const TimerGroup &TG) LLVM_DELETED_FUNCTION; + void operator=(const TimerGroup &TG) LLVM_DELETED_FUNCTION; public: explicit TimerGroup(StringRef name); ~TimerGroup(); diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h index e147647..a1397db 100644 --- a/include/llvm/Support/Valgrind.h +++ b/include/llvm/Support/Valgrind.h @@ -16,8 +16,8 @@ #ifndef LLVM_SYSTEM_VALGRIND_H #define LLVM_SYSTEM_VALGRIND_H -#include "llvm/Support/Compiler.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Support/Compiler.h" #include <stddef.h> #if LLVM_ENABLE_THREADS != 0 && !defined(NDEBUG) diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index 61e21b8..db44995 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -16,7 +16,7 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/Value.h" +#include "llvm/IR/Value.h" namespace llvm { class ValueHandleBase; @@ -59,8 +59,8 @@ private: // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this // access. PointerIntPair<Value*, 2> VP; - - explicit ValueHandleBase(const ValueHandleBase&); // DO NOT IMPLEMENT. + + ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; public: explicit ValueHandleBase(HandleBaseKind Kind) : PrevPair(0, Kind), Next(0), VP(0, 0) {} diff --git a/include/llvm/Support/Win64EH.h b/include/llvm/Support/Win64EH.h index 8d74e10..164aca1 100644 --- a/include/llvm/Support/Win64EH.h +++ b/include/llvm/Support/Win64EH.h @@ -17,6 +17,7 @@ #define LLVM_SUPPORT_WIN64EH_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Endian.h" namespace llvm { namespace Win64EH { @@ -39,11 +40,17 @@ enum UnwindOpcodes { /// or part thereof. union UnwindCode { struct { - uint8_t codeOffset; - uint8_t unwindOp:4, - opInfo:4; + support::ulittle8_t CodeOffset; + support::ulittle8_t UnwindOpAndOpInfo; } u; - uint16_t frameOffset; + support::ulittle16_t FrameOffset; + + uint8_t getUnwindOp() const { + return u.UnwindOpAndOpInfo & 0x0F; + } + uint8_t getOpInfo() const { + return (u.UnwindOpAndOpInfo >> 4) & 0x0F; + } }; enum { @@ -60,37 +67,65 @@ enum { /// RuntimeFunction - An entry in the table of functions with unwind info. struct RuntimeFunction { - uint64_t startAddress; - uint64_t endAddress; - uint64_t unwindInfoOffset; + support::ulittle32_t StartAddress; + support::ulittle32_t EndAddress; + support::ulittle32_t UnwindInfoOffset; }; /// UnwindInfo - An entry in the exception table. struct UnwindInfo { - uint8_t version:3, - flags:5; - uint8_t prologSize; - uint8_t numCodes; - uint8_t frameRegister:4, - frameOffset:4; - UnwindCode unwindCodes[1]; + support::ulittle8_t VersionAndFlags; + support::ulittle8_t PrologSize; + support::ulittle8_t NumCodes; + support::ulittle8_t FrameRegisterAndOffset; + UnwindCode UnwindCodes[1]; - void *getLanguageSpecificData() { - return reinterpret_cast<void *>(&unwindCodes[(numCodes+1) & ~1]); + uint8_t getVersion() const { + return VersionAndFlags & 0x07; } - uint64_t getLanguageSpecificHandlerOffset() { - return *reinterpret_cast<uint64_t *>(getLanguageSpecificData()); + uint8_t getFlags() const { + return (VersionAndFlags >> 3) & 0x1f; } - void setLanguageSpecificHandlerOffset(uint64_t offset) { - *reinterpret_cast<uint64_t *>(getLanguageSpecificData()) = offset; + uint8_t getFrameRegister() const { + return FrameRegisterAndOffset & 0x0f; } - RuntimeFunction *getChainedFunctionEntry() { - return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData()); + uint8_t getFrameOffset() const { + return (FrameRegisterAndOffset >> 4) & 0x0f; + } + + // The data after unwindCodes depends on flags. + // If UNW_ExceptionHandler or UNW_TerminateHandler is set then follows + // the address of the language-specific exception handler. + // If UNW_ChainInfo is set then follows a RuntimeFunction which defines + // the chained unwind info. + // For more information please see MSDN at: + // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx + + /// \brief Return pointer to language specific data part of UnwindInfo. + void *getLanguageSpecificData() { + return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]); } + + /// \brief Return image-relativ offset of language-specific exception handler. + uint32_t getLanguageSpecificHandlerOffset() { + return *reinterpret_cast<uint32_t *>(getLanguageSpecificData()); + } + + /// \brief Set image-relativ offset of language-specific exception handler. + void setLanguageSpecificHandlerOffset(uint32_t offset) { + *reinterpret_cast<uint32_t *>(getLanguageSpecificData()) = offset; + } + + /// \brief Return pointer to exception-specific data. void *getExceptionData() { - return reinterpret_cast<void *>(reinterpret_cast<uint64_t *>( + return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>( getLanguageSpecificData())+1); } + + /// \brief Return pointer to chained unwind info. + RuntimeFunction *getChainedFunctionEntry() { + return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData()); + } }; diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 98910eb..5b728bc 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -43,7 +43,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/SMLoc.h" - #include <limits> #include <utility> @@ -77,7 +76,11 @@ std::string escape(StringRef Input); /// documents. class Stream { public: + /// @brief This keeps a reference to the string referenced by \p Input. Stream(StringRef Input, SourceMgr &); + + /// @brief This takes ownership of \p InputBuffer. + Stream(MemoryBuffer *InputBuffer, SourceMgr &); ~Stream(); document_iterator begin(); @@ -133,7 +136,6 @@ public: virtual void skip() {} unsigned int getType() const { return TypeID; } - static inline bool classof(const Node *) { return true; } void *operator new ( size_t Size , BumpPtrAllocator &Alloc @@ -166,7 +168,6 @@ class NullNode : public Node { public: NullNode(OwningPtr<Document> &D) : Node(NK_Null, D, StringRef()) {} - static inline bool classof(const NullNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_Null; } @@ -183,7 +184,7 @@ public: : Node(NK_Scalar, D, Anchor) , Value(Val) { SMLoc Start = SMLoc::getFromPointer(Val.begin()); - SMLoc End = SMLoc::getFromPointer(Val.end() - 1); + SMLoc End = SMLoc::getFromPointer(Val.end()); SourceRange = SMRange(Start, End); } @@ -199,7 +200,6 @@ public: /// This happens with escaped characters and multi-line literals. StringRef getValue(SmallVectorImpl<char> &Storage) const; - static inline bool classof(const ScalarNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_Scalar; } @@ -241,12 +241,11 @@ public: /// @returns The value, or nullptr if failed() == true. Node *getValue(); - virtual void skip() { + virtual void skip() LLVM_OVERRIDE { getKey()->skip(); getValue()->skip(); } - static inline bool classof(const KeyValueNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_KeyValue; } @@ -358,11 +357,10 @@ public: iterator end() { return iterator(); } - virtual void skip() { + virtual void skip() LLVM_OVERRIDE { yaml::skip(*this); } - static inline bool classof(const MappingNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_Mapping; } @@ -421,11 +419,10 @@ public: iterator end() { return iterator(); } - virtual void skip() { + virtual void skip() LLVM_OVERRIDE { yaml::skip(*this); } - static inline bool classof(const SequenceNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_Sequence; } @@ -450,7 +447,6 @@ public: StringRef getName() const { return Name; } Node *getTarget(); - static inline bool classof(const ScalarNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_Alias; } diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h new file mode 100644 index 0000000..1862286 --- /dev/null +++ b/include/llvm/Support/YAMLTraits.h @@ -0,0 +1,1104 @@ +//===- llvm/Supporrt/YAMLTraits.h -------------------------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_YAML_TRAITS_H_ +#define LLVM_YAML_TRAITS_H_ + + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLParser.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/type_traits.h" + + +namespace llvm { +namespace yaml { + + +/// This class should be specialized by any type that needs to be converted +/// to/from a YAML mapping. For example: +/// +/// struct ScalarBitSetTraits<MyStruct> { +/// static void mapping(IO &io, MyStruct &s) { +/// io.mapRequired("name", s.name); +/// io.mapRequired("size", s.size); +/// io.mapOptional("age", s.age); +/// } +/// }; +template<class T> +struct MappingTraits { + // Must provide: + // static void mapping(IO &io, T &fields); +}; + + +/// This class should be specialized by any integral type that converts +/// to/from a YAML scalar where there is a one-to-one mapping between +/// in-memory values and a string in YAML. For example: +/// +/// struct ScalarEnumerationTraits<Colors> { +/// static void enumeration(IO &io, Colors &value) { +/// io.enumCase(value, "red", cRed); +/// io.enumCase(value, "blue", cBlue); +/// io.enumCase(value, "green", cGreen); +/// } +/// }; +template<typename T> +struct ScalarEnumerationTraits { + // Must provide: + // static void enumeration(IO &io, T &value); +}; + + +/// This class should be specialized by any integer type that is a union +/// of bit values and the YAML representation is a flow sequence of +/// strings. For example: +/// +/// struct ScalarBitSetTraits<MyFlags> { +/// static void bitset(IO &io, MyFlags &value) { +/// io.bitSetCase(value, "big", flagBig); +/// io.bitSetCase(value, "flat", flagFlat); +/// io.bitSetCase(value, "round", flagRound); +/// } +/// }; +template<typename T> +struct ScalarBitSetTraits { + // Must provide: + // static void bitset(IO &io, T &value); +}; + + +/// This class should be specialized by type that requires custom conversion +/// to/from a yaml scalar. For example: +/// +/// template<> +/// struct ScalarTraits<MyType> { +/// static void output(const MyType &val, void*, llvm::raw_ostream &out) { +/// // stream out custom formatting +/// out << llvm::format("%x", val); +/// } +/// static StringRef input(StringRef scalar, void*, MyType &value) { +/// // parse scalar and set `value` +/// // return empty string on success, or error string +/// return StringRef(); +/// } +/// }; +template<typename T> +struct ScalarTraits { + // Must provide: + // + // Function to write the value as a string: + //static void output(const T &value, void *ctxt, llvm::raw_ostream &out); + // + // Function to convert a string to a value. Returns the empty + // StringRef on success or an error string if string is malformed: + //static StringRef input(StringRef scalar, void *ctxt, T &value); +}; + + +/// This class should be specialized by any type that needs to be converted +/// to/from a YAML sequence. For example: +/// +/// template<> +/// struct SequenceTraits< std::vector<MyType> > { +/// static size_t size(IO &io, std::vector<MyType> &seq) { +/// return seq.size(); +/// } +/// static MyType& element(IO &, std::vector<MyType> &seq, size_t index) { +/// if ( index >= seq.size() ) +/// seq.resize(index+1); +/// return seq[index]; +/// } +/// }; +template<typename T> +struct SequenceTraits { + // Must provide: + // static size_t size(IO &io, T &seq); + // static T::value_type& element(IO &io, T &seq, size_t index); + // + // The following is option and will cause generated YAML to use + // a flow sequence (e.g. [a,b,c]). + // static const bool flow = true; +}; + + +/// This class should be specialized by any type that needs to be converted +/// to/from a list of YAML documents. +template<typename T> +struct DocumentListTraits { + // Must provide: + // static size_t size(IO &io, T &seq); + // static T::value_type& element(IO &io, T &seq, size_t index); +}; + + +// Only used by compiler if both template types are the same +template <typename T, T> +struct SameType; + +// Only used for better diagnostics of missing traits +template <typename T> +struct MissingTrait; + + + +// Test if ScalarEnumerationTraits<T> is defined on type T. +template <class T> +struct has_ScalarEnumerationTraits +{ + typedef void (*Signature_enumeration)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_enumeration, &U::enumeration>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<ScalarEnumerationTraits<T> >(0)) == 1); +}; + + +// Test if ScalarBitSetTraits<T> is defined on type T. +template <class T> +struct has_ScalarBitSetTraits +{ + typedef void (*Signature_bitset)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_bitset, &U::bitset>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(0)) == 1); +}; + + +// Test if ScalarTraits<T> is defined on type T. +template <class T> +struct has_ScalarTraits +{ + typedef llvm::StringRef (*Signature_input)(llvm::StringRef, void*, T&); + typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&); + + template <typename U> + static char test(SameType<Signature_input, &U::input>*, + SameType<Signature_output, &U::output>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<ScalarTraits<T> >(0,0)) == 1); +}; + + +// Test if MappingTraits<T> is defined on type T. +template <class T> +struct has_MappingTraits +{ + typedef void (*Signature_mapping)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_mapping, &U::mapping>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1); +}; + + +// Test if SequenceTraits<T> is defined on type T. +template <class T> +struct has_SequenceMethodTraits +{ + typedef size_t (*Signature_size)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_size, &U::size>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<SequenceTraits<T> >(0)) == 1); +}; + + +// has_FlowTraits<int> will cause an error with some compilers because +// it subclasses int. Using this wrapper only instantiates the +// real has_FlowTraits only if the template type is a class. +template <typename T, bool Enabled = llvm::is_class<T>::value> +class has_FlowTraits +{ +public: + static const bool value = false; +}; + +// Some older gcc compilers don't support straight forward tests +// for members, so test for ambiguity cause by the base and derived +// classes both defining the member. +template <class T> +struct has_FlowTraits<T, true> +{ + struct Fallback { bool flow; }; + struct Derived : T, Fallback { }; + + template<typename C> + static char (&f(SameType<bool Fallback::*, &C::flow>*))[1]; + + template<typename C> + static char (&f(...))[2]; + +public: + static bool const value = sizeof(f<Derived>(0)) == 2; +}; + + + +// Test if SequenceTraits<T> is defined on type T +template<typename T> +struct has_SequenceTraits : public llvm::integral_constant<bool, + has_SequenceMethodTraits<T>::value > { }; + + +// Test if DocumentListTraits<T> is defined on type T +template <class T> +struct has_DocumentListTraits +{ + typedef size_t (*Signature_size)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_size, &U::size>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<DocumentListTraits<T> >(0)) == 1); +}; + + + + +template<typename T> +struct missingTraits : public llvm::integral_constant<bool, + !has_ScalarEnumerationTraits<T>::value + && !has_ScalarBitSetTraits<T>::value + && !has_ScalarTraits<T>::value + && !has_MappingTraits<T>::value + && !has_SequenceTraits<T>::value + && !has_DocumentListTraits<T>::value > {}; + + +// Base class for Input and Output. +class IO { +public: + + IO(void *Ctxt=NULL); + virtual ~IO(); + + virtual bool outputting() = 0; + + virtual unsigned beginSequence() = 0; + virtual bool preflightElement(unsigned, void *&) = 0; + virtual void postflightElement(void*) = 0; + virtual void endSequence() = 0; + + virtual unsigned beginFlowSequence() = 0; + virtual bool preflightFlowElement(unsigned, void *&) = 0; + virtual void postflightFlowElement(void*) = 0; + virtual void endFlowSequence() = 0; + + virtual void beginMapping() = 0; + virtual void endMapping() = 0; + virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; + virtual void postflightKey(void*) = 0; + + virtual void beginEnumScalar() = 0; + virtual bool matchEnumScalar(const char*, bool) = 0; + virtual void endEnumScalar() = 0; + + virtual bool beginBitSetScalar(bool &) = 0; + virtual bool bitSetMatch(const char*, bool) = 0; + virtual void endBitSetScalar() = 0; + + virtual void scalarString(StringRef &) = 0; + + virtual void setError(const Twine &) = 0; + + template <typename T> + void enumCase(T &Val, const char* Str, const T ConstVal) { + if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) { + Val = ConstVal; + } + } + + // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF + template <typename T> + void enumCase(T &Val, const char* Str, const uint32_t ConstVal) { + if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) { + Val = ConstVal; + } + } + + template <typename T> + void bitSetCase(T &Val, const char* Str, const T ConstVal) { + if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { + Val = Val | ConstVal; + } + } + + // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF + template <typename T> + void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) { + if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { + Val = Val | ConstVal; + } + } + + void *getContext(); + void setContext(void *); + + template <typename T> + void mapRequired(const char* Key, T& Val) { + this->processKey(Key, Val, true); + } + + template <typename T> + 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()) ) + return; + this->processKey(Key, Val, false); + } + + template <typename T> + typename llvm::enable_if_c<!has_SequenceTraits<T>::value,void>::type + mapOptional(const char* Key, T& Val) { + this->processKey(Key, Val, false); + } + + template <typename T> + 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, + bool Required) { + void *SaveInfo; + bool UseDefault; + const bool sameAsDefault = outputting() && Val == DefaultValue; + if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault, + SaveInfo) ) { + yamlize(*this, Val, Required); + this->postflightKey(SaveInfo); + } + else { + if ( UseDefault ) + Val = DefaultValue; + } + } + + template <typename T> + void processKey(const char *Key, T &Val, bool Required) { + void *SaveInfo; + bool UseDefault; + if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) { + yamlize(*this, Val, Required); + this->postflightKey(SaveInfo); + } + } + +private: + void *Ctxt; +}; + + + +template<typename T> +typename llvm::enable_if_c<has_ScalarEnumerationTraits<T>::value,void>::type +yamlize(IO &io, T &Val, bool) { + io.beginEnumScalar(); + ScalarEnumerationTraits<T>::enumeration(io, Val); + io.endEnumScalar(); +} + +template<typename T> +typename llvm::enable_if_c<has_ScalarBitSetTraits<T>::value,void>::type +yamlize(IO &io, T &Val, bool) { + bool DoClear; + if ( io.beginBitSetScalar(DoClear) ) { + if ( DoClear ) + Val = static_cast<T>(0); + ScalarBitSetTraits<T>::bitset(io, Val); + io.endBitSetScalar(); + } +} + + +template<typename T> +typename llvm::enable_if_c<has_ScalarTraits<T>::value,void>::type +yamlize(IO &io, T &Val, bool) { + if ( io.outputting() ) { + std::string Storage; + llvm::raw_string_ostream Buffer(Storage); + ScalarTraits<T>::output(Val, io.getContext(), Buffer); + StringRef Str = Buffer.str(); + io.scalarString(Str); + } + else { + StringRef Str; + io.scalarString(Str); + StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val); + if ( !Result.empty() ) { + io.setError(llvm::Twine(Result)); + } + } +} + + +template<typename T> +typename llvm::enable_if_c<has_MappingTraits<T>::value, void>::type +yamlize(IO &io, T &Val, bool) { + io.beginMapping(); + MappingTraits<T>::mapping(io, Val); + io.endMapping(); +} + +template<typename T> +typename llvm::enable_if_c<missingTraits<T>::value, void>::type +yamlize(IO &io, T &Val, bool) { + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; +} + +template<typename T> +typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type +yamlize(IO &io, T &Seq, bool) { + if ( has_FlowTraits< SequenceTraits<T> >::value ) { + unsigned incnt = io.beginFlowSequence(); + unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; + for(unsigned i=0; i < count; ++i) { + void *SaveInfo; + if ( io.preflightFlowElement(i, SaveInfo) ) { + yamlize(io, SequenceTraits<T>::element(io, Seq, i), true); + io.postflightFlowElement(SaveInfo); + } + } + io.endFlowSequence(); + } + else { + unsigned incnt = io.beginSequence(); + unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; + for(unsigned i=0; i < count; ++i) { + void *SaveInfo; + if ( io.preflightElement(i, SaveInfo) ) { + yamlize(io, SequenceTraits<T>::element(io, Seq, i), true); + io.postflightElement(SaveInfo); + } + } + io.endSequence(); + } +} + + +template<> +struct ScalarTraits<bool> { + static void output(const bool &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, bool &); +}; + +template<> +struct ScalarTraits<StringRef> { + static void output(const StringRef &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, StringRef &); +}; + +template<> +struct ScalarTraits<uint8_t> { + static void output(const uint8_t &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, uint8_t &); +}; + +template<> +struct ScalarTraits<uint16_t> { + static void output(const uint16_t &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, uint16_t &); +}; + +template<> +struct ScalarTraits<uint32_t> { + static void output(const uint32_t &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, uint32_t &); +}; + +template<> +struct ScalarTraits<uint64_t> { + static void output(const uint64_t &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, uint64_t &); +}; + +template<> +struct ScalarTraits<int8_t> { + static void output(const int8_t &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, int8_t &); +}; + +template<> +struct ScalarTraits<int16_t> { + static void output(const int16_t &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, int16_t &); +}; + +template<> +struct ScalarTraits<int32_t> { + static void output(const int32_t &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, int32_t &); +}; + +template<> +struct ScalarTraits<int64_t> { + static void output(const int64_t &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, int64_t &); +}; + +template<> +struct ScalarTraits<float> { + static void output(const float &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, float &); +}; + +template<> +struct ScalarTraits<double> { + static void output(const double &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, double &); +}; + + + +// Utility for use within MappingTraits<>::mapping() method +// to [de]normalize an object for use with YAML conversion. +template <typename TNorm, typename TFinal> +struct MappingNormalization { + MappingNormalization(IO &i_o, TFinal &Obj) + : io(i_o), BufPtr(NULL), Result(Obj) { + if ( io.outputting() ) { + BufPtr = new (&Buffer) TNorm(io, Obj); + } + else { + BufPtr = new (&Buffer) TNorm(io); + } + } + + ~MappingNormalization() { + if ( ! io.outputting() ) { + Result = BufPtr->denormalize(io); + } + BufPtr->~TNorm(); + } + + TNorm* operator->() { return BufPtr; } + +private: + typedef llvm::AlignedCharArrayUnion<TNorm> Storage; + + Storage Buffer; + IO &io; + TNorm *BufPtr; + TFinal &Result; +}; + + + +// Utility for use within MappingTraits<>::mapping() method +// to [de]normalize an object for use with YAML conversion. +template <typename TNorm, typename TFinal> +struct MappingNormalizationHeap { + MappingNormalizationHeap(IO &i_o, TFinal &Obj) + : io(i_o), BufPtr(NULL), Result(Obj) { + if ( io.outputting() ) { + BufPtr = new (&Buffer) TNorm(io, Obj); + } + else { + BufPtr = new TNorm(io); + } + } + + ~MappingNormalizationHeap() { + if ( io.outputting() ) { + BufPtr->~TNorm(); + } + else { + Result = BufPtr->denormalize(io); + } + } + + TNorm* operator->() { return BufPtr; } + +private: + typedef llvm::AlignedCharArrayUnion<TNorm> Storage; + + Storage Buffer; + IO &io; + TNorm *BufPtr; + TFinal &Result; +}; + + + +/// +/// The Input class is used to parse a yaml document into in-memory structs +/// and vectors. +/// +/// It works by using YAMLParser to do a syntax parse of the entire yaml +/// document, then the Input class builds a graph of HNodes which wraps +/// each yaml Node. The extra layer is buffering. The low level yaml +/// parser only lets you look at each node once. The buffering layer lets +/// you search and interate multiple times. This is necessary because +/// the mapRequired() method calls may not be in the same order +/// as the keys in the document. +/// +class Input : public IO { +public: + // Construct a yaml Input object from a StringRef and optional user-data. + Input(StringRef InputContent, void *Ctxt=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); + +private: + virtual bool outputting(); + virtual void beginMapping(); + virtual void endMapping(); + virtual bool preflightKey(const char *, bool, bool, bool &, void *&); + virtual void postflightKey(void *); + virtual unsigned beginSequence(); + virtual void endSequence(); + virtual bool preflightElement(unsigned index, void *&); + virtual void postflightElement(void *); + virtual unsigned beginFlowSequence(); + virtual bool preflightFlowElement(unsigned , void *&); + virtual void postflightFlowElement(void *); + virtual void endFlowSequence(); + virtual void beginEnumScalar(); + virtual bool matchEnumScalar(const char*, bool); + virtual void endEnumScalar(); + virtual bool beginBitSetScalar(bool &); + virtual bool bitSetMatch(const char *, bool ); + virtual void endBitSetScalar(); + virtual void scalarString(StringRef &); + virtual void setError(const Twine &message); + + class HNode { + public: + HNode(Node *n) : _node(n) { } + virtual ~HNode() { } + static inline bool classof(const HNode *) { return true; } + + Node *_node; + }; + + class EmptyHNode : public HNode { + public: + EmptyHNode(Node *n) : HNode(n) { } + virtual ~EmptyHNode() {} + static inline bool classof(const HNode *n) { + return NullNode::classof(n->_node); + } + static inline bool classof(const EmptyHNode *) { return true; } + }; + + class ScalarHNode : public HNode { + public: + ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } + virtual ~ScalarHNode() { } + + StringRef value() const { return _value; } + + static inline bool classof(const HNode *n) { + return ScalarNode::classof(n->_node); + } + static inline bool classof(const ScalarHNode *) { return true; } + protected: + StringRef _value; + }; + + class MapHNode : public HNode { + public: + MapHNode(Node *n) : HNode(n) { } + virtual ~MapHNode(); + + static inline bool classof(const HNode *n) { + return MappingNode::classof(n->_node); + } + static inline bool classof(const MapHNode *) { return true; } + + struct StrMappingInfo { + static StringRef getEmptyKey() { return StringRef(); } + static StringRef getTombstoneKey() { return StringRef(" ", 0); } + static unsigned getHashValue(StringRef const val) { + return llvm::HashString(val); } + static bool isEqual(StringRef const lhs, + StringRef const rhs) { return lhs.equals(rhs); } + }; + typedef llvm::DenseMap<StringRef, HNode*, StrMappingInfo> NameToNode; + + bool isValidKey(StringRef key); + + NameToNode Mapping; + llvm::SmallVector<const char*, 6> ValidKeys; + }; + + class SequenceHNode : public HNode { + public: + SequenceHNode(Node *n) : HNode(n) { } + virtual ~SequenceHNode(); + + static inline bool classof(const HNode *n) { + return SequenceNode::classof(n->_node); + } + static inline bool classof(const SequenceHNode *) { return true; } + + std::vector<HNode*> Entries; + }; + + Input::HNode *createHNodes(Node *node); + void setError(HNode *hnode, const Twine &message); + void setError(Node *node, const Twine &message); + + +public: + // These are only used by operator>>. They could be private + // if those templated things could be made friends. + bool setCurrentDocument(); + void nextDocument(); + +private: + llvm::SourceMgr SrcMgr; // must be before Strm + OwningPtr<llvm::yaml::Stream> Strm; + OwningPtr<HNode> TopNode; + llvm::error_code EC; + llvm::BumpPtrAllocator StringAllocator; + llvm::yaml::document_iterator DocIterator; + std::vector<bool> BitValuesUsed; + HNode *CurrentNode; + bool ScalarMatchFound; +}; + + + + +/// +/// The Output class is used to generate a yaml document from in-memory structs +/// and vectors. +/// +class Output : public IO { +public: + Output(llvm::raw_ostream &, void *Ctxt=NULL); + virtual ~Output(); + + virtual bool outputting(); + virtual void beginMapping(); + virtual void endMapping(); + virtual bool preflightKey(const char *key, bool, bool, bool &, void *&); + virtual void postflightKey(void *); + virtual unsigned beginSequence(); + virtual void endSequence(); + virtual bool preflightElement(unsigned, void *&); + virtual void postflightElement(void *); + virtual unsigned beginFlowSequence(); + virtual bool preflightFlowElement(unsigned, void *&); + virtual void postflightFlowElement(void *); + virtual void endFlowSequence(); + virtual void beginEnumScalar(); + virtual bool matchEnumScalar(const char*, bool); + virtual void endEnumScalar(); + virtual bool beginBitSetScalar(bool &); + virtual bool bitSetMatch(const char *, bool ); + virtual void endBitSetScalar(); + virtual void scalarString(StringRef &); + virtual void setError(const Twine &message); + +public: + // These are only used by operator<<. They could be private + // if that templated operator could be made a friend. + void beginDocuments(); + bool preflightDocument(unsigned); + void postflightDocument(); + void endDocuments(); + +private: + void output(StringRef s); + void outputUpToEndOfLine(StringRef s); + void newLineCheck(); + void outputNewLine(); + void paddedKey(StringRef key); + + enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey }; + + llvm::raw_ostream &Out; + SmallVector<InState, 8> StateStack; + int Column; + int ColumnAtFlowStart; + bool NeedBitValueComma; + bool NeedFlowSequenceComma; + bool EnumerationMatchFound; + bool NeedsNewLine; +}; + + + + +/// YAML I/O does conversion based on types. But often native data types +/// are just a typedef of built in intergral types (e.g. int). But the C++ +/// type matching system sees through the typedef and all the typedefed types +/// look like a built in type. This will cause the generic YAML I/O conversion +/// to be used. To provide better control over the YAML conversion, you can +/// use this macro instead of typedef. It will create a class with one field +/// and automatic conversion operators to and from the base type. +/// Based on BOOST_STRONG_TYPEDEF +#define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \ + struct _type { \ + _type() { } \ + _type(const _base v) : value(v) { } \ + _type(const _type &v) : value(v.value) {} \ + _type &operator=(const _type &rhs) { value = rhs.value; return *this; }\ + _type &operator=(const _base &rhs) { value = rhs; return *this; } \ + operator const _base & () const { return value; } \ + bool operator==(const _type &rhs) const { return value == rhs.value; } \ + bool operator==(const _base &rhs) const { return value == rhs; } \ + bool operator<(const _type &rhs) const { return value < rhs.value; } \ + _base value; \ + }; + + + +/// +/// Use these types instead of uintXX_t in any mapping to have +/// its yaml output formatted as hexadecimal. +/// +LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8) +LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32) +LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64) + + +template<> +struct ScalarTraits<Hex8> { + static void output(const Hex8 &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, Hex8 &); +}; + +template<> +struct ScalarTraits<Hex16> { + static void output(const Hex16 &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, Hex16 &); +}; + +template<> +struct ScalarTraits<Hex32> { + static void output(const Hex32 &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, Hex32 &); +}; + +template<> +struct ScalarTraits<Hex64> { + static void output(const Hex64 &, void*, llvm::raw_ostream &); + static llvm::StringRef input(llvm::StringRef , void*, Hex64 &); +}; + + +// Define non-member operator>> so that Input can stream in a document list. +template <typename T> +inline +typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Input &>::type +operator>>(Input &yin, T &docList) { + int i = 0; + while ( yin.setCurrentDocument() ) { + yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true); + if ( yin.error() ) + return yin; + yin.nextDocument(); + ++i; + } + return yin; +} + +// Define non-member operator>> so that Input can stream in a map as a document. +template <typename T> +inline +typename llvm::enable_if_c<has_MappingTraits<T>::value,Input &>::type +operator>>(Input &yin, T &docMap) { + yin.setCurrentDocument(); + yamlize(yin, docMap, true); + return yin; +} + +// Define non-member operator>> so that Input can stream in a sequence as +// a document. +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); + return yin; +} + +// Provide better error message about types missing a trait specialization +template <typename T> +inline +typename llvm::enable_if_c<missingTraits<T>::value,Input &>::type +operator>>(Input &yin, T &docSeq) { + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; + return yin; +} + + +// Define non-member operator<< so that Output can stream out document list. +template <typename T> +inline +typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Output &>::type +operator<<(Output &yout, T &docList) { + yout.beginDocuments(); + const size_t count = DocumentListTraits<T>::size(yout, docList); + for(size_t i=0; i < count; ++i) { + if ( yout.preflightDocument(i) ) { + yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true); + yout.postflightDocument(); + } + } + yout.endDocuments(); + return yout; +} + +// Define non-member operator<< so that Output can stream out a map. +template <typename T> +inline +typename llvm::enable_if_c<has_MappingTraits<T>::value,Output &>::type +operator<<(Output &yout, T &map) { + yout.beginDocuments(); + if ( yout.preflightDocument(0) ) { + yamlize(yout, map, true); + yout.postflightDocument(); + } + yout.endDocuments(); + return yout; +} + +// Define non-member operator<< so that Output can stream out a sequence. +template <typename T> +inline +typename llvm::enable_if_c<has_SequenceTraits<T>::value,Output &>::type +operator<<(Output &yout, T &seq) { + yout.beginDocuments(); + if ( yout.preflightDocument(0) ) { + yamlize(yout, seq, true); + yout.postflightDocument(); + } + yout.endDocuments(); + return yout; +} + +// Provide better error message about types missing a trait specialization +template <typename T> +inline +typename llvm::enable_if_c<missingTraits<T>::value,Output &>::type +operator<<(Output &yout, T &seq) { + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; + return yout; +} + + +} // namespace yaml +} // namespace llvm + + +/// Utility for declaring that a std::vector of a particular type +/// should be considered a YAML sequence. +#define LLVM_YAML_IS_SEQUENCE_VECTOR(_type) \ + namespace llvm { \ + namespace yaml { \ + template<> \ + struct SequenceTraits< std::vector<_type> > { \ + static size_t size(IO &io, std::vector<_type> &seq) { \ + return seq.size(); \ + } \ + static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ + if ( index >= seq.size() ) \ + seq.resize(index+1); \ + return seq[index]; \ + } \ + }; \ + } \ + } + +/// Utility for declaring that a std::vector of a particular type +/// should be considered a YAML flow sequence. +#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type) \ + namespace llvm { \ + namespace yaml { \ + template<> \ + struct SequenceTraits< std::vector<_type> > { \ + static size_t size(IO &io, std::vector<_type> &seq) { \ + return seq.size(); \ + } \ + static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ + if ( index >= seq.size() ) \ + seq.resize(index+1); \ + return seq[index]; \ + } \ + static const bool flow = true; \ + }; \ + } \ + } + +/// Utility for declaring that a std::vector of a particular type +/// should be considered a YAML document list. +#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \ + namespace llvm { \ + namespace yaml { \ + template<> \ + struct DocumentListTraits< std::vector<_type> > { \ + static size_t size(IO &io, std::vector<_type> &seq) { \ + return seq.size(); \ + } \ + static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ + if ( index >= seq.size() ) \ + seq.resize(index+1); \ + return seq[index]; \ + } \ + }; \ + } \ + } + + + +#endif // LLVM_YAML_TRAITS_H_ diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h index 2b3c329..9000306 100644 --- a/include/llvm/Support/circular_raw_ostream.h +++ b/include/llvm/Support/circular_raw_ostream.h @@ -71,7 +71,7 @@ namespace llvm /// flushBuffer - Dump the contents of the buffer to Stream. /// - void flushBuffer(void) { + void flushBuffer() { if (Filled) // Write the older portion of the buffer. TheStream->write(Cur, BufferArray + BufferSize - Cur); @@ -81,12 +81,12 @@ namespace llvm Filled = false; } - virtual void write_impl(const char *Ptr, size_t Size); + virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; /// current_pos - Return the current position within the stream, /// not counting the bytes currently in the buffer. /// - virtual uint64_t current_pos() const { + virtual uint64_t current_pos() const LLVM_OVERRIDE { // This has the same effect as calling TheStream.current_pos(), // but that interface is private. return TheStream->tell() - TheStream->GetNumBytesInBuffer(); @@ -151,7 +151,7 @@ namespace llvm /// flushBufferWithBanner - Force output of the buffer along with /// a small header. /// - void flushBufferWithBanner(void); + void flushBufferWithBanner(); private: /// releaseStream - Delete the held stream if needed. Otherwise, diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h index 4f5d361..4385721 100644 --- a/include/llvm/Support/raw_os_ostream.h +++ b/include/llvm/Support/raw_os_ostream.h @@ -24,14 +24,14 @@ namespace llvm { /// use the underlying stream to detect errors. class raw_os_ostream : public raw_ostream { std::ostream &OS; - + /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size); - + virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const; - + virtual uint64_t current_pos() const LLVM_OVERRIDE; + public: raw_os_ostream(std::ostream &O) : OS(O) {} ~raw_os_ostream(); diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 9913f98..eab0f2d 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -15,6 +15,7 @@ #define LLVM_SUPPORT_RAW_OSTREAM_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -29,8 +30,8 @@ namespace llvm { class raw_ostream { private: // Do not implement. raw_ostream is noncopyable. - void operator=(const raw_ostream &); - raw_ostream(const raw_ostream &); + void operator=(const raw_ostream &) LLVM_DELETED_FUNCTION; + raw_ostream(const raw_ostream &) LLVM_DELETED_FUNCTION; /// The buffer is handled in such a way that the buffer is /// uninitialized, unbuffered, or out of space when OutBufCur >= @@ -191,10 +192,10 @@ public: raw_ostream &operator<<(double N); - /// write_hex - Output \arg N in hexadecimal, without any prefix or padding. + /// write_hex - Output \p N in hexadecimal, without any prefix or padding. raw_ostream &write_hex(unsigned long long N); - /// write_escaped - Output \arg Str, turning '\\', '\t', '\n', '"', and + /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and /// anything that doesn't satisfy std::isprint into an escape sequence. raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); @@ -218,6 +219,9 @@ public: virtual raw_ostream &changeColor(enum Colors Color, bool Bold = false, bool BG = false) { + (void)Color; + (void)Bold; + (void)BG; return *this; } @@ -242,15 +246,16 @@ public: private: /// write_impl - The is the piece of the class that is implemented - /// by subclasses. This writes the \args Size bytes starting at - /// \arg Ptr to the underlying stream. + /// by subclasses. This writes the \p Size bytes starting at + /// \p Ptr to the underlying stream. /// /// This function is guaranteed to only be called at a point at which it is /// safe for the subclass to install a new buffer via SetBuffer. /// - /// \arg Ptr - The start of the data to be written. For buffered streams this + /// \param Ptr The start of the data to be written. For buffered streams this /// is guaranteed to be the start of the buffer. - /// \arg Size - The number of bytes to be written. + /// + /// \param Size The number of bytes to be written. /// /// \invariant { Size > 0 } virtual void write_impl(const char *Ptr, size_t Size) = 0; @@ -317,14 +322,14 @@ class raw_fd_ostream : public raw_ostream { uint64_t pos; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size); + virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const { return pos; } + virtual uint64_t current_pos() const LLVM_OVERRIDE { return pos; } /// preferred_buffer_size - Determine an efficient buffer size. - virtual size_t preferred_buffer_size() const; + virtual size_t preferred_buffer_size() const LLVM_OVERRIDE; /// error_detected - Set the flag indicating that an output error has /// been encountered. @@ -385,14 +390,14 @@ public: } virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, - bool bg=false); - virtual raw_ostream &resetColor(); + bool bg=false) LLVM_OVERRIDE; + virtual raw_ostream &resetColor() LLVM_OVERRIDE; - virtual raw_ostream &reverseColor(); + virtual raw_ostream &reverseColor() LLVM_OVERRIDE; - virtual bool is_displayed() const; + virtual bool is_displayed() const LLVM_OVERRIDE; - virtual bool has_colors() const; + virtual bool has_colors() const LLVM_OVERRIDE; /// has_error - Return the value of the flag in this raw_fd_ostream indicating /// whether an output error has been encountered. @@ -438,11 +443,11 @@ class raw_string_ostream : public raw_ostream { std::string &OS; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size); + virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const { return OS.size(); } + virtual uint64_t current_pos() const LLVM_OVERRIDE { return OS.size(); } public: explicit raw_string_ostream(std::string &O) : OS(O) {} ~raw_string_ostream(); @@ -462,15 +467,15 @@ class raw_svector_ostream : public raw_ostream { SmallVectorImpl<char> &OS; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size); + virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const; + virtual uint64_t current_pos() const LLVM_OVERRIDE; public: /// Construct a new raw_svector_ostream. /// - /// \arg O - The vector to write to; this should generally have at least 128 + /// \param O The vector to write to; this should generally have at least 128 /// bytes free to avoid any extraneous memory overhead. explicit raw_svector_ostream(SmallVectorImpl<char> &O); ~raw_svector_ostream(); @@ -488,11 +493,11 @@ public: /// raw_null_ostream - A raw_ostream that discards all output. class raw_null_ostream : public raw_ostream { /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t size); + virtual void write_impl(const char *Ptr, size_t size) LLVM_OVERRIDE; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const; + virtual uint64_t current_pos() const LLVM_OVERRIDE; public: explicit raw_null_ostream() {} diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h index af81206..0d164f6 100644 --- a/include/llvm/Support/system_error.h +++ b/include/llvm/Support/system_error.h @@ -17,6 +17,8 @@ #ifndef LLVM_SYSTEM_SYSTEM_ERROR_H #define LLVM_SYSTEM_SYSTEM_ERROR_H +#include "llvm/Support/Compiler.h" + /* system_error synopsis @@ -629,8 +631,8 @@ public: private: error_category(); - error_category(const error_category&);// = delete; - error_category& operator=(const error_category&);// = delete; + error_category(const error_category&) LLVM_DELETED_FUNCTION; + error_category& operator=(const error_category&) LLVM_DELETED_FUNCTION; public: virtual const char* name() const = 0; @@ -651,7 +653,7 @@ public: class _do_message : public error_category { public: - virtual std::string message(int ev) const; + virtual std::string message(int ev) const LLVM_OVERRIDE; }; const error_category& generic_category(); diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 7b97547..f930639 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -54,8 +54,9 @@ struct is_class // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For // more details: // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1 - public: - enum { value = sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)) }; +public: + static const bool value = + sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)); }; @@ -162,12 +163,11 @@ template <typename T> class is_integral_or_enum { static UnderlyingT &nonce_instance; public: - enum { + static const bool value = (!is_class<UnderlyingT>::value && !is_pointer<UnderlyingT>::value && !is_same<UnderlyingT, float>::value && !is_same<UnderlyingT, double>::value && - sizeof(char) != sizeof(check_int_convertible(nonce_instance))) - }; + sizeof(char) != sizeof(check_int_convertible(nonce_instance))); }; // enable_if_c - Enable/disable a template based on a metafunction diff --git a/include/llvm/TableGen/Error.h b/include/llvm/TableGen/Error.h index 5c1c3ad..2f6b7e6 100644 --- a/include/llvm/TableGen/Error.h +++ b/include/llvm/TableGen/Error.h @@ -19,27 +19,17 @@ namespace llvm { -class TGError { - SmallVector<SMLoc, 4> Locs; - std::string Message; -public: - TGError(ArrayRef<SMLoc> locs, const std::string &message) - : Locs(locs.begin(), locs.end()), Message(message) {} - - ArrayRef<SMLoc> getLoc() const { return Locs; } - const std::string &getMessage() const { return Message; } -}; - void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg); void PrintWarning(const char *Loc, const Twine &Msg); void PrintWarning(const Twine &Msg); -void PrintWarning(const TGError &Warning); void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg); void PrintError(const char *Loc, const Twine &Msg); void PrintError(const Twine &Msg); -void PrintError(const TGError &Error); +LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const std::string &Msg); +LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, + const std::string &Msg); extern SourceMgr SrcMgr; diff --git a/include/llvm/TableGen/Main.h b/include/llvm/TableGen/Main.h index deaef4a..6b51e20 100644 --- a/include/llvm/TableGen/Main.h +++ b/include/llvm/TableGen/Main.h @@ -16,10 +16,13 @@ namespace llvm { -class TableGenAction; +class RecordKeeper; +class raw_ostream; +/// \brief Perform the action using Records, and write output to OS. +/// \returns true on error, false otherwise +typedef bool TableGenMainFn(raw_ostream &OS, RecordKeeper &Records); -/// Run the table generator, performing the specified Action on parsed records. -int TableGenMain(char *argv0, TableGenAction &Action); +int TableGenMain(char *argv0, TableGenMainFn *MainFn); } diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index adb1a77..8968534 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -18,9 +18,10 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include <map> @@ -66,10 +67,27 @@ class RecordKeeper; //===----------------------------------------------------------------------===// class RecTy { +public: + /// \brief Subclass discriminator (for dyn_cast<> et al.) + enum RecTyKind { + BitRecTyKind, + BitsRecTyKind, + IntRecTyKind, + StringRecTyKind, + ListRecTyKind, + DagRecTyKind, + RecordRecTyKind + }; + +private: + RecTyKind Kind; ListRecTy *ListTy; virtual void anchor(); + public: - RecTy() : ListTy(0) {} + RecTyKind getRecTyKind() const { return Kind; } + + RecTy(RecTyKind K) : Kind(K), ListTy(0) {} virtual ~RecTy() {} virtual std::string getAsString() const = 0; @@ -110,16 +128,8 @@ public: // These methods should only be called from subclasses of Init return convertValue((TypedInit*)FI); } -public: // These methods should only be called by subclasses of RecTy. - // baseClassOf - These virtual methods should be overloaded to return true iff - // all values of type 'RHS' can be converted to the 'this' type. - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } +public: + virtual bool baseClassOf(const RecTy*) const; }; inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { @@ -132,8 +142,12 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { /// class BitRecTy : public RecTy { static BitRecTy Shared; - BitRecTy() {} + BitRecTy() : RecTy(BitRecTyKind) {} public: + static bool classof(const RecTy *RT) { + return RT->getRecTyKind() == BitRecTyKind; + } + static BitRecTy *get() { return &Shared; } virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } @@ -152,19 +166,12 @@ public: virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - std::string getAsString() const { return "bit"; } + virtual std::string getAsString() const { return "bit"; } - bool typeIsConvertibleTo(const RecTy *RHS) const { + virtual bool typeIsConvertibleTo(const RecTy *RHS) const { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const BitRecTy *RHS) const { return true; } - virtual bool baseClassOf(const BitsRecTy *RHS) const; - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } - + virtual bool baseClassOf(const RecTy*) const; }; @@ -173,8 +180,12 @@ public: /// class BitsRecTy : public RecTy { unsigned Size; - explicit BitsRecTy(unsigned Sz) : Size(Sz) {} + explicit BitsRecTy(unsigned Sz) : RecTy(BitsRecTyKind), Size(Sz) {} public: + static bool classof(const RecTy *RT) { + return RT->getRecTyKind() == BitsRecTyKind; + } + static BitsRecTy *get(unsigned Sz); unsigned getNumBits() const { return Size; } @@ -195,21 +206,12 @@ public: virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - std::string getAsString() const; + virtual std::string getAsString() const; - bool typeIsConvertibleTo(const RecTy *RHS) const { + virtual bool typeIsConvertibleTo(const RecTy *RHS) const { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { - return RHS->Size == Size; - } - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } - + virtual bool baseClassOf(const RecTy*) const; }; @@ -217,8 +219,12 @@ public: /// class IntRecTy : public RecTy { static IntRecTy Shared; - IntRecTy() {} + IntRecTy() : RecTy(IntRecTyKind) {} public: + static bool classof(const RecTy *RT) { + return RT->getRecTyKind() == IntRecTyKind; + } + static IntRecTy *get() { return &Shared; } virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } @@ -237,28 +243,25 @@ public: virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - std::string getAsString() const { return "int"; } + virtual std::string getAsString() const { return "int"; } - bool typeIsConvertibleTo(const RecTy *RHS) const { + virtual bool typeIsConvertibleTo(const RecTy *RHS) const { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const BitRecTy *RHS) const { return true; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } - + virtual bool baseClassOf(const RecTy*) const; }; /// StringRecTy - 'string' - Represent an string value /// class StringRecTy : public RecTy { static StringRecTy Shared; - StringRecTy() {} + StringRecTy() : RecTy(StringRecTyKind) {} public: + static bool classof(const RecTy *RT) { + return RT->getRecTyKind() == StringRecTyKind; + } + static StringRecTy *get() { return &Shared; } virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } @@ -278,19 +281,11 @@ public: virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - std::string getAsString() const { return "string"; } + virtual std::string getAsString() const { return "string"; } - bool typeIsConvertibleTo(const RecTy *RHS) const { + virtual bool typeIsConvertibleTo(const RecTy *RHS) const { return RHS->baseClassOf(this); } - - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return true; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } }; // ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of @@ -300,9 +295,13 @@ public: /// class ListRecTy : public RecTy { RecTy *Ty; - explicit ListRecTy(RecTy *T) : Ty(T) {} + explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), Ty(T) {} friend ListRecTy *RecTy::getListTy(); public: + static bool classof(const RecTy *RT) { + return RT->getRecTyKind() == ListRecTyKind; + } + static ListRecTy *get(RecTy *T) { return T->getListTy(); } RecTy *getElementType() const { return Ty; } @@ -322,29 +321,25 @@ public: virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - std::string getAsString() const; + virtual std::string getAsString() const; - bool typeIsConvertibleTo(const RecTy *RHS) const { + virtual bool typeIsConvertibleTo(const RecTy *RHS) const { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { - return RHS->getElementType()->typeIsConvertibleTo(Ty); - } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecTy*) const; }; /// DagRecTy - 'dag' - Represent a dag fragment /// class DagRecTy : public RecTy { static DagRecTy Shared; - DagRecTy() {} + DagRecTy() : RecTy(DagRecTyKind) {} public: + static bool classof(const RecTy *RT) { + return RT->getRecTyKind() == DagRecTyKind; + } + static DagRecTy *get() { return &Shared; } virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } @@ -363,19 +358,11 @@ public: virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - std::string getAsString() const { return "dag"; } + virtual std::string getAsString() const { return "dag"; } - bool typeIsConvertibleTo(const RecTy *RHS) const { + virtual bool typeIsConvertibleTo(const RecTy *RHS) const { return RHS->baseClassOf(this); } - - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return true; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } }; @@ -384,9 +371,13 @@ public: /// class RecordRecTy : public RecTy { Record *Rec; - explicit RecordRecTy(Record *R) : Rec(R) {} + explicit RecordRecTy(Record *R) : RecTy(RecordRecTyKind), Rec(R) {} friend class Record; public: + static bool classof(const RecTy *RT) { + return RT->getRecTyKind() == RecordRecTyKind; + } + static RecordRecTy *get(Record *R); Record *getRecord() const { return Rec; } @@ -407,18 +398,12 @@ public: virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - std::string getAsString() const; + virtual std::string getAsString() const; - bool typeIsConvertibleTo(const RecTy *RHS) const { + virtual bool typeIsConvertibleTo(const RecTy *RHS) const { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const; + virtual bool baseClassOf(const RecTy*) const; }; /// resolveTypes - Find a common type that T1 and T2 convert to. @@ -431,12 +416,53 @@ RecTy *resolveTypes(RecTy *T1, RecTy *T2); //===----------------------------------------------------------------------===// class Init { - Init(const Init &); // Do not define. - Init &operator=(const Init &); // Do not define. +protected: + /// \brief Discriminator enum (for isa<>, dyn_cast<>, et al.) + /// + /// This enum is laid out by a preorder traversal of the inheritance + /// hierarchy, and does not contain an entry for abstract classes, as per + /// the recommendation in docs/HowToSetUpLLVMStyleRTTI.rst. + /// + /// We also explicitly include "first" and "last" values for each + /// interior node of the inheritance tree, to make it easier to read the + /// corresponding classof(). + /// + /// We could pack these a bit tighter by not having the IK_FirstXXXInit + /// and IK_LastXXXInit be their own values, but that would degrade + /// readability for really no benefit. + enum InitKind { + IK_BitInit, + IK_BitsInit, + IK_FirstTypedInit, + IK_DagInit, + IK_DefInit, + IK_FieldInit, + IK_IntInit, + IK_ListInit, + IK_FirstOpInit, + IK_BinOpInit, + IK_TernOpInit, + IK_UnOpInit, + IK_LastOpInit, + IK_StringInit, + IK_VarInit, + IK_VarListElementInit, + IK_LastTypedInit, + IK_UnsetInit, + IK_VarBitInit + }; + +private: + const InitKind Kind; + Init(const Init &) LLVM_DELETED_FUNCTION; + Init &operator=(const Init &) LLVM_DELETED_FUNCTION; virtual void anchor(); +public: + InitKind getKind() const { return Kind; } + protected: - Init(void) {} + explicit Init(InitKind K) : Kind(K) {} public: virtual ~Init() {} @@ -533,13 +559,17 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { class TypedInit : public Init { RecTy *Ty; - TypedInit(const TypedInit &Other); // Do not define. - TypedInit &operator=(const TypedInit &Other); // Do not define. + TypedInit(const TypedInit &Other) LLVM_DELETED_FUNCTION; + TypedInit &operator=(const TypedInit &Other) LLVM_DELETED_FUNCTION; protected: - explicit TypedInit(RecTy *T) : Ty(T) {} + explicit TypedInit(InitKind K, RecTy *T) : Init(K), Ty(T) {} public: + static bool classof(const Init *I) { + return I->getKind() >= IK_FirstTypedInit && + I->getKind() <= IK_LastTypedInit; + } RecTy *getType() const { return Ty; } virtual Init * @@ -564,12 +594,15 @@ public: /// UnsetInit - ? - Represents an uninitialized value /// class UnsetInit : public Init { - UnsetInit() : Init() {} - UnsetInit(const UnsetInit &); // Do not define. - UnsetInit &operator=(const UnsetInit &Other); // Do not define. + UnsetInit() : Init(IK_UnsetInit) {} + UnsetInit(const UnsetInit &) LLVM_DELETED_FUNCTION; + UnsetInit &operator=(const UnsetInit &Other) LLVM_DELETED_FUNCTION; virtual void anchor(); public: + static bool classof(const Init *I) { + return I->getKind() == IK_UnsetInit; + } static UnsetInit *get(); virtual Init *convertInitializerTo(RecTy *Ty) const { @@ -590,12 +623,15 @@ public: class BitInit : public Init { bool Value; - explicit BitInit(bool V) : Value(V) {} - BitInit(const BitInit &Other); // Do not define. - BitInit &operator=(BitInit &Other); // Do not define. + explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {} + BitInit(const BitInit &Other) LLVM_DELETED_FUNCTION; + BitInit &operator=(BitInit &Other) LLVM_DELETED_FUNCTION; virtual void anchor(); public: + static bool classof(const Init *I) { + return I->getKind() == IK_BitInit; + } static BitInit *get(bool V); bool getValue() const { return Value; } @@ -618,12 +654,16 @@ public: class BitsInit : public Init, public FoldingSetNode { std::vector<Init*> Bits; - BitsInit(ArrayRef<Init *> Range) : Bits(Range.begin(), Range.end()) {} + BitsInit(ArrayRef<Init *> Range) + : Init(IK_BitsInit), Bits(Range.begin(), Range.end()) {} - BitsInit(const BitsInit &Other); // Do not define. - BitsInit &operator=(const BitsInit &Other); // Do not define. + BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION; + BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_BitsInit; + } static BitsInit *get(ArrayRef<Init *> Range); void Profile(FoldingSetNodeID &ID) const; @@ -662,12 +702,16 @@ public: class IntInit : public TypedInit { int64_t Value; - explicit IntInit(int64_t V) : TypedInit(IntRecTy::get()), Value(V) {} + explicit IntInit(int64_t V) + : TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {} - IntInit(const IntInit &Other); // Do not define. - IntInit &operator=(const IntInit &Other); // Do note define. + IntInit(const IntInit &Other) LLVM_DELETED_FUNCTION; + IntInit &operator=(const IntInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_IntInit; + } static IntInit *get(int64_t V); int64_t getValue() const { return Value; } @@ -700,13 +744,16 @@ class StringInit : public TypedInit { std::string Value; explicit StringInit(const std::string &V) - : TypedInit(StringRecTy::get()), Value(V) {} + : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {} - StringInit(const StringInit &Other); // Do not define. - StringInit &operator=(const StringInit &Other); // Do not define. + StringInit(const StringInit &Other) LLVM_DELETED_FUNCTION; + StringInit &operator=(const StringInit &Other) LLVM_DELETED_FUNCTION; virtual void anchor(); public: + static bool classof(const Init *I) { + return I->getKind() == IK_StringInit; + } static StringInit *get(StringRef); const std::string &getValue() const { return Value; } @@ -740,12 +787,16 @@ public: private: explicit ListInit(ArrayRef<Init *> Range, RecTy *EltTy) - : TypedInit(ListRecTy::get(EltTy)), Values(Range.begin(), Range.end()) {} + : TypedInit(IK_ListInit, ListRecTy::get(EltTy)), + Values(Range.begin(), Range.end()) {} - ListInit(const ListInit &Other); // Do not define. - ListInit &operator=(const ListInit &Other); // Do not define. + ListInit(const ListInit &Other) LLVM_DELETED_FUNCTION; + ListInit &operator=(const ListInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_ListInit; + } static ListInit *get(ArrayRef<Init *> Range, RecTy *EltTy); void Profile(FoldingSetNodeID &ID) const; @@ -758,7 +809,8 @@ public: Record *getElementAsRecord(unsigned i) const; - Init *convertInitListSlice(const std::vector<unsigned> &Elements) const; + virtual Init * + convertInitListSlice(const std::vector<unsigned> &Elements) const; virtual Init *convertInitializerTo(RecTy *Ty) const { return Ty->convertValue(const_cast<ListInit *>(this)); @@ -796,13 +848,17 @@ public: /// OpInit - Base class for operators /// class OpInit : public TypedInit { - OpInit(const OpInit &Other); // Do not define. - OpInit &operator=(OpInit &Other); // Do not define. + OpInit(const OpInit &Other) LLVM_DELETED_FUNCTION; + OpInit &operator=(OpInit &Other) LLVM_DELETED_FUNCTION; protected: - explicit OpInit(RecTy *Type) : TypedInit(Type) {} + explicit OpInit(InitKind K, RecTy *Type) : TypedInit(K, Type) {} public: + static bool classof(const Init *I) { + return I->getKind() >= IK_FirstOpInit && + I->getKind() <= IK_LastOpInit; + } // Clone - Clone this operator, replacing arguments with the new list virtual OpInit *clone(std::vector<Init *> &Operands) const = 0; @@ -834,12 +890,15 @@ private: Init *LHS; UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) - : OpInit(Type), Opc(opc), LHS(lhs) {} + : OpInit(IK_UnOpInit, Type), Opc(opc), LHS(lhs) {} - UnOpInit(const UnOpInit &Other); // Do not define. - UnOpInit &operator=(const UnOpInit &Other); // Do not define. + UnOpInit(const UnOpInit &Other) LLVM_DELETED_FUNCTION; + UnOpInit &operator=(const UnOpInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_UnOpInit; + } static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type); // Clone - Clone this operator, replacing arguments with the new list @@ -849,8 +908,8 @@ public: return UnOpInit::get(getOpcode(), *Operands.begin(), getType()); } - int getNumOperands() const { return 1; } - Init *getOperand(int i) const { + virtual int getNumOperands() const { return 1; } + virtual Init *getOperand(int i) const { assert(i == 0 && "Invalid operand id for unary operator"); return getOperand(); } @@ -860,7 +919,7 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; @@ -877,12 +936,15 @@ private: Init *LHS, *RHS; BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) : - OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {} + OpInit(IK_BinOpInit, Type), Opc(opc), LHS(lhs), RHS(rhs) {} - BinOpInit(const BinOpInit &Other); // Do not define. - BinOpInit &operator=(const BinOpInit &Other); // Do not define. + BinOpInit(const BinOpInit &Other) LLVM_DELETED_FUNCTION; + BinOpInit &operator=(const BinOpInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_BinOpInit; + } static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type); @@ -893,8 +955,8 @@ public: return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType()); } - int getNumOperands() const { return 2; } - Init *getOperand(int i) const { + virtual int getNumOperands() const { return 2; } + virtual Init *getOperand(int i) const { assert((i == 0 || i == 1) && "Invalid operand id for binary operator"); if (i == 0) { return getLHS(); @@ -909,7 +971,7 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; @@ -927,12 +989,15 @@ private: TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, RecTy *Type) : - OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {} + OpInit(IK_TernOpInit, Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {} - TernOpInit(const TernOpInit &Other); // Do not define. - TernOpInit &operator=(const TernOpInit &Other); // Do not define. + TernOpInit(const TernOpInit &Other) LLVM_DELETED_FUNCTION; + TernOpInit &operator=(const TernOpInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_TernOpInit; + } static TernOpInit *get(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, RecTy *Type); @@ -945,8 +1010,8 @@ public: getType()); } - int getNumOperands() const { return 3; } - Init *getOperand(int i) const { + virtual int getNumOperands() const { return 3; } + virtual Init *getOperand(int i) const { assert((i == 0 || i == 1 || i == 2) && "Invalid operand id for ternary operator"); if (i == 0) { @@ -965,7 +1030,7 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; virtual bool isComplete() const { return false; } @@ -981,14 +1046,17 @@ class VarInit : public TypedInit { Init *VarName; explicit VarInit(const std::string &VN, RecTy *T) - : TypedInit(T), VarName(StringInit::get(VN)) {} + : TypedInit(IK_VarInit, T), VarName(StringInit::get(VN)) {} explicit VarInit(Init *VN, RecTy *T) - : TypedInit(T), VarName(VN) {} + : TypedInit(IK_VarInit, T), VarName(VN) {} - VarInit(const VarInit &Other); // Do not define. - VarInit &operator=(const VarInit &Other); // Do not define. + VarInit(const VarInit &Other) LLVM_DELETED_FUNCTION; + VarInit &operator=(const VarInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_VarInit; + } static VarInit *get(const std::string &VN, RecTy *T); static VarInit *get(Init *VN, RecTy *T); @@ -1028,18 +1096,21 @@ class VarBitInit : public Init { TypedInit *TI; unsigned Bit; - VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) { + VarBitInit(TypedInit *T, unsigned B) : Init(IK_VarBitInit), TI(T), Bit(B) { assert(T->getType() && - (dynamic_cast<IntRecTy*>(T->getType()) || - (dynamic_cast<BitsRecTy*>(T->getType()) && - dynamic_cast<BitsRecTy*>(T->getType())->getNumBits() > B)) && + (isa<IntRecTy>(T->getType()) || + (isa<BitsRecTy>(T->getType()) && + cast<BitsRecTy>(T->getType())->getNumBits() > B)) && "Illegal VarBitInit expression!"); } - VarBitInit(const VarBitInit &Other); // Do not define. - VarBitInit &operator=(const VarBitInit &Other); // Do not define. + VarBitInit(const VarBitInit &Other) LLVM_DELETED_FUNCTION; + VarBitInit &operator=(const VarBitInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_VarBitInit; + } static VarBitInit *get(TypedInit *T, unsigned B); virtual Init *convertInitializerTo(RecTy *Ty) const { @@ -1065,18 +1136,20 @@ class VarListElementInit : public TypedInit { unsigned Element; VarListElementInit(TypedInit *T, unsigned E) - : TypedInit(dynamic_cast<ListRecTy*>(T->getType())->getElementType()), - TI(T), Element(E) { - assert(T->getType() && dynamic_cast<ListRecTy*>(T->getType()) && + : TypedInit(IK_VarListElementInit, + cast<ListRecTy>(T->getType())->getElementType()), + TI(T), Element(E) { + assert(T->getType() && isa<ListRecTy>(T->getType()) && "Illegal VarBitInit expression!"); } - VarListElementInit(const VarListElementInit &Other); // Do not define. - VarListElementInit &operator=(const VarListElementInit &Other); // Do - // not - // define. + VarListElementInit(const VarListElementInit &Other) LLVM_DELETED_FUNCTION; + void operator=(const VarListElementInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_VarListElementInit; + } static VarListElementInit *get(TypedInit *T, unsigned E); virtual Init *convertInitializerTo(RecTy *Ty) const { @@ -1104,13 +1177,16 @@ public: class DefInit : public TypedInit { Record *Def; - DefInit(Record *D, RecordRecTy *T) : TypedInit(T), Def(D) {} + DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {} friend class Record; - DefInit(const DefInit &Other); // Do not define. - DefInit &operator=(const DefInit &Other); // Do not define. + DefInit(const DefInit &Other) LLVM_DELETED_FUNCTION; + DefInit &operator=(const DefInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_DefInit; + } static DefInit *get(Record*); virtual Init *convertInitializerTo(RecTy *Ty) const { @@ -1148,14 +1224,17 @@ class FieldInit : public TypedInit { std::string FieldName; // Field we are accessing FieldInit(Init *R, const std::string &FN) - : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) { + : TypedInit(IK_FieldInit, R->getFieldType(FN)), Rec(R), FieldName(FN) { assert(getType() && "FieldInit with non-record type!"); } - FieldInit(const FieldInit &Other); // Do not define. - FieldInit &operator=(const FieldInit &Other); // Do not define. + FieldInit(const FieldInit &Other) LLVM_DELETED_FUNCTION; + FieldInit &operator=(const FieldInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_FieldInit; + } static FieldInit *get(Init *R, const std::string &FN); static FieldInit *get(Init *R, const Init *FN); @@ -1189,14 +1268,17 @@ class DagInit : public TypedInit, public FoldingSetNode { DagInit(Init *V, const std::string &VN, ArrayRef<Init *> ArgRange, ArrayRef<std::string> NameRange) - : TypedInit(DagRecTy::get()), Val(V), ValName(VN), + : TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN), Args(ArgRange.begin(), ArgRange.end()), ArgNames(NameRange.begin(), NameRange.end()) {} - DagInit(const DagInit &Other); // Do not define. - DagInit &operator=(const DagInit &Other); // Do not define. + DagInit(const DagInit &Other) LLVM_DELETED_FUNCTION; + DagInit &operator=(const DagInit &Other) LLVM_DELETED_FUNCTION; public: + static bool classof(const Init *I) { + return I->getKind() == IK_DagInit; + } static DagInit *get(Init *V, const std::string &VN, ArrayRef<Init *> ArgRange, ArrayRef<std::string> NameRange); @@ -1329,6 +1411,14 @@ public: TrackedRecords(records), TheInit(0) { init(); } + + // When copy-constructing a Record, we must still guarantee a globally unique + // ID number. All other fields can be copied normally. + Record(const Record &O) : + ID(LastID++), Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs), + Values(O.Values), SuperClasses(O.SuperClasses), + TrackedRecords(O.TrackedRecords), TheInit(O.TheInit) { } + ~Record() {} @@ -1610,6 +1700,16 @@ struct LessRecord { } }; +/// LessRecordByID - Sorting predicate to sort record pointers by their +/// unique ID. If you just need a deterministic order, use this, since it +/// just compares two `unsigned`; the other sorting predicates require +/// string manipulation. +struct LessRecordByID { + bool operator()(const Record *LHS, const Record *RHS) const { + return LHS->getID() < RHS->getID(); + } +}; + /// LessRecordFieldName - Sorting predicate to sort record pointers by their /// name field. /// diff --git a/include/llvm/TableGen/StringMatcher.h b/include/llvm/TableGen/StringMatcher.h index 1dadc76..1b0572f 100644 --- a/include/llvm/TableGen/StringMatcher.h +++ b/include/llvm/TableGen/StringMatcher.h @@ -14,10 +14,10 @@ #ifndef STRINGMATCHER_H #define STRINGMATCHER_H -#include <vector> +#include "llvm/ADT/StringRef.h" #include <string> #include <utility> -#include "llvm/ADT/StringRef.h" +#include <vector> namespace llvm { class raw_ostream; diff --git a/include/llvm/TableGen/TableGenAction.h b/include/llvm/TableGen/TableGenAction.h deleted file mode 100644 index 733ae62..0000000 --- a/include/llvm/TableGen/TableGenAction.h +++ /dev/null @@ -1,35 +0,0 @@ -//===- llvm/TableGen/TableGenAction.h - defines TableGenAction --*- 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 TableGenAction base class to be derived from by -// tblgen tools. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TABLEGEN_TABLEGENACTION_H -#define LLVM_TABLEGEN_TABLEGENACTION_H - -namespace llvm { - -class raw_ostream; -class RecordKeeper; - -class TableGenAction { - virtual void anchor(); -public: - virtual ~TableGenAction() {} - - /// Perform the action using Records, and write output to OS. - /// @returns true on error, false otherwise - virtual bool operator()(raw_ostream &OS, RecordKeeper &Records) = 0; -}; - -} - -#endif diff --git a/include/llvm/Target/Mangler.h b/include/llvm/Target/Mangler.h index d5e165e..a50f54a 100644 --- a/include/llvm/Target/Mangler.h +++ b/include/llvm/Target/Mangler.h @@ -22,7 +22,7 @@ class GlobalValue; template <typename T> class SmallVectorImpl; class MCContext; class MCSymbol; -class TargetData; +class DataLayout; class Mangler { public: @@ -34,7 +34,7 @@ public: private: MCContext &Context; - const TargetData &TD; + const DataLayout &TD; /// AnonGlobalIDs - We need to give global values the same name every time /// they are mangled. This keeps track of the number we give to anonymous @@ -47,20 +47,19 @@ private: unsigned NextAnonGlobalID; public: - Mangler(MCContext &context, const TargetData &td) + Mangler(MCContext &context, const DataLayout &td) : Context(context), TD(td), 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); - /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix /// and the specified global variable's name. If the global variable doesn't /// have a name, this fills in a unique name for the global. void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV, bool isImplicitlyPrivate); - + /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix /// and the specified name as the global variable name. GVName must not be /// empty. diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 87bd84e..1781e47 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// // Include all information about LLVM intrinsics. -include "llvm/Intrinsics.td" +include "llvm/IR/Intrinsics.td" //===----------------------------------------------------------------------===// // Register file description - These classes are used to fill in the target @@ -495,7 +495,8 @@ def ptr_rc : PointerLikeRegClass<0>; /// unknown definition - Mark this operand as being of unknown type, causing /// it to be resolved by inference in the context it is used. -def unknown; +class unknown_class; +def unknown : unknown_class; /// AsmOperandClass - Representation for the kinds of operands which the target /// specific parser can create and the assembly matcher may need to distinguish. @@ -988,12 +989,64 @@ class Processor<string n, ProcessorItineraries pi, list<SubtargetFeature> f> { // ProcessorModel allows subtargets to specify the more general // SchedMachineModel instead if a ProcessorItinerary. Subtargets will // gradually move to this newer form. +// +// Although this class always passes NoItineraries to the Processor +// class, the SchedMachineModel may still define valid Itineraries. class ProcessorModel<string n, SchedMachineModel m, list<SubtargetFeature> f> : Processor<n, NoItineraries, f> { let SchedModel = m; } //===----------------------------------------------------------------------===// +// InstrMapping - This class is used to create mapping tables to relate +// instructions with each other based on the values specified in RowFields, +// ColFields, KeyCol and ValueCols. +// +class InstrMapping { + // FilterClass - Used to limit search space only to the instructions that + // define the relationship modeled by this InstrMapping record. + string FilterClass; + + // RowFields - List of fields/attributes that should be same for all the + // instructions in a row of the relation table. Think of this as a set of + // properties shared by all the instructions related by this relationship + // model and is used to categorize instructions into subgroups. For instance, + // if we want to define a relation that maps 'Add' instruction to its + // predicated forms, we can define RowFields like this: + // + // let RowFields = BaseOp + // All add instruction predicated/non-predicated will have to set their BaseOp + // to the same value. + // + // def Add: { let BaseOp = 'ADD'; let predSense = 'nopred' } + // def Add_predtrue: { let BaseOp = 'ADD'; let predSense = 'true' } + // def Add_predfalse: { let BaseOp = 'ADD'; let predSense = 'false' } + list<string> RowFields = []; + + // List of fields/attributes that are same for all the instructions + // in a column of the relation table. + // Ex: let ColFields = 'predSense' -- It means that the columns are arranged + // based on the 'predSense' values. All the instruction in a specific + // column have the same value and it is fixed for the column according + // to the values set in 'ValueCols'. + list<string> ColFields = []; + + // Values for the fields/attributes listed in 'ColFields'. + // Ex: let KeyCol = 'nopred' -- It means that the key instruction (instruction + // that models this relation) should be non-predicated. + // In the example above, 'Add' is the key instruction. + list<string> KeyCol = []; + + // List of values for the fields/attributes listed in 'ColFields', one for + // each column in the relation table. + // + // Ex: let ValueCols = [['true'],['false']] -- It adds two columns in the + // table. First column requires all the instructions to have predSense + // set to 'true' and second column requires it to be 'false'. + list<list<string> > ValueCols = []; +} + +//===----------------------------------------------------------------------===// // Pull in the common support for calling conventions. // include "llvm/Target/TargetCallingConv.td" diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index f8cebef..2160e37 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -113,9 +113,18 @@ namespace ISD { MVT VT; bool Used; + /// Index original Function's argument. + unsigned OrigArgIndex; + + /// Offset in bytes of current input value relative to the beginning of + /// original argument. E.g. if argument was splitted into four 32 bit + /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12. + unsigned PartOffset; + InputArg() : VT(MVT::Other), Used(false) {} - InputArg(ArgFlagsTy flags, EVT vt, bool used) - : Flags(flags), Used(used) { + InputArg(ArgFlagsTy flags, EVT vt, bool used, + unsigned origIdx, unsigned partOffs) + : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) { VT = vt.getSimpleVT(); } }; @@ -131,9 +140,19 @@ namespace ISD { /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...". bool IsFixed; + /// Index original Function's argument. + unsigned OrigArgIndex; + + /// Offset in bytes of current output value relative to the beginning of + /// original argument. E.g. if argument was splitted into four 32 bit + /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12. + unsigned PartOffset; + OutputArg() : IsFixed(false) {} - OutputArg(ArgFlagsTy flags, EVT vt, bool isfixed) - : Flags(flags), IsFixed(isfixed) { + OutputArg(ArgFlagsTy flags, EVT vt, bool isfixed, + unsigned origIdx, unsigned partOffs) + : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx), + PartOffset(partOffs) { VT = vt.getSimpleVT(); } }; diff --git a/include/llvm/Target/TargetELFWriterInfo.h b/include/llvm/Target/TargetELFWriterInfo.h deleted file mode 100644 index 5e48629..0000000 --- a/include/llvm/Target/TargetELFWriterInfo.h +++ /dev/null @@ -1,121 +0,0 @@ -//===-- llvm/Target/TargetELFWriterInfo.h - ELF Writer Info -----*- 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 TargetELFWriterInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETELFWRITERINFO_H -#define LLVM_TARGET_TARGETELFWRITERINFO_H - -namespace llvm { - - //===--------------------------------------------------------------------===// - // TargetELFWriterInfo - //===--------------------------------------------------------------------===// - - class TargetELFWriterInfo { - protected: - // EMachine - This field is the target specific value to emit as the - // e_machine member of the ELF header. - unsigned short EMachine; - bool is64Bit, isLittleEndian; - public: - - // Machine architectures - enum MachineType { - EM_NONE = 0, // No machine - EM_M32 = 1, // AT&T WE 32100 - EM_SPARC = 2, // SPARC - EM_386 = 3, // Intel 386 - EM_68K = 4, // Motorola 68000 - EM_88K = 5, // Motorola 88000 - EM_486 = 6, // Intel 486 (deprecated) - EM_860 = 7, // Intel 80860 - EM_MIPS = 8, // MIPS R3000 - EM_PPC = 20, // PowerPC - EM_ARM = 40, // ARM - EM_ALPHA = 41, // DEC Alpha - EM_SPARCV9 = 43, // SPARC V9 - EM_X86_64 = 62, // AMD64 - EM_HEXAGON = 164 // Qualcomm Hexagon - }; - - // ELF File classes - enum { - ELFCLASS32 = 1, // 32-bit object file - ELFCLASS64 = 2 // 64-bit object file - }; - - // ELF Endianess - enum { - ELFDATA2LSB = 1, // Little-endian object file - ELFDATA2MSB = 2 // Big-endian object file - }; - - explicit TargetELFWriterInfo(bool is64Bit_, bool isLittleEndian_); - virtual ~TargetELFWriterInfo(); - - unsigned short getEMachine() const { return EMachine; } - unsigned getEFlags() const { return 0; } - unsigned getEIClass() const { return is64Bit ? ELFCLASS64 : ELFCLASS32; } - unsigned getEIData() const { - return isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; - } - - /// ELF Header and ELF Section Header Info - unsigned getHdrSize() const { return is64Bit ? 64 : 52; } - unsigned getSHdrSize() const { return is64Bit ? 64 : 40; } - - /// Symbol Table Info - unsigned getSymTabEntrySize() const { return is64Bit ? 24 : 16; } - - /// getPrefELFAlignment - Returns the preferred alignment for ELF. This - /// is used to align some sections. - unsigned getPrefELFAlignment() const { return is64Bit ? 8 : 4; } - - /// getRelocationEntrySize - Entry size used in the relocation section - unsigned getRelocationEntrySize() const { - return is64Bit ? (hasRelocationAddend() ? 24 : 16) - : (hasRelocationAddend() ? 12 : 8); - } - - /// getRelocationType - Returns the target specific ELF Relocation type. - /// 'MachineRelTy' contains the object code independent relocation type - virtual unsigned getRelocationType(unsigned MachineRelTy) const = 0; - - /// hasRelocationAddend - True if the target uses an addend in the - /// ELF relocation entry. - virtual bool hasRelocationAddend() const = 0; - - /// getDefaultAddendForRelTy - Gets the default addend value for a - /// relocation entry based on the target ELF relocation type. - virtual long int getDefaultAddendForRelTy(unsigned RelTy, - long int Modifier = 0) const = 0; - - /// getRelTySize - Returns the size of relocatable field in bits - virtual unsigned getRelocationTySize(unsigned RelTy) const = 0; - - /// isPCRelativeRel - True if the relocation type is pc relative - virtual bool isPCRelativeRel(unsigned RelTy) const = 0; - - /// getJumpTableRelocationTy - Returns the machine relocation type used - /// to reference a jumptable. - virtual unsigned getAbsoluteLabelMachineRelTy() const = 0; - - /// computeRelocation - Some relocatable fields could be relocated - /// directly, avoiding the relocation symbol emission, compute the - /// final relocation value for this symbol. - virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset, - unsigned RelTy) const = 0; - }; - -} // end llvm namespace - -#endif // LLVM_TARGET_TARGETELFWRITERINFO_H diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index d56db7b..1958f90 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -15,7 +15,6 @@ #define LLVM_TARGET_TARGETFRAMELOWERING_H #include "llvm/CodeGen/MachineBasicBlock.h" - #include <utility> #include <vector> @@ -48,11 +47,12 @@ private: unsigned StackAlignment; unsigned TransientStackAlignment; int LocalAreaOffset; + bool StackRealignable; public: TargetFrameLowering(StackDirection D, unsigned StackAl, int LAO, - unsigned TransAl = 1) + unsigned TransAl = 1, bool StackReal = true) : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), - LocalAreaOffset(LAO) {} + LocalAreaOffset(LAO), StackRealignable(StackReal) {} virtual ~TargetFrameLowering(); @@ -77,6 +77,12 @@ public: return TransientStackAlignment; } + /// isStackRealignable - This method returns whether the stack can be + /// realigned. + bool isStackRealignable() const { + return StackRealignable; + } + /// getOffsetOfLocalArea - This method returns the offset of the local area /// from the stack pointer on entrance to a function. /// diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index d7cc1cf..fb311d8 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -15,9 +15,9 @@ #define LLVM_TARGET_TARGETINSTRINFO_H #include "llvm/ADT/SmallSet.h" -#include "llvm/MC/MCInstrInfo.h" #include "llvm/CodeGen/DFAPacketizer.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/MC/MCInstrInfo.h" namespace llvm { @@ -45,8 +45,8 @@ template<class T> class SmallVectorImpl; /// TargetInstrInfo - Interface to description of machine instruction set /// class TargetInstrInfo : public MCInstrInfo { - TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT - void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT + TargetInstrInfo(const TargetInstrInfo &) LLVM_DELETED_FUNCTION; + void operator=(const TargetInstrInfo &) LLVM_DELETED_FUNCTION; public: TargetInstrInfo(int CFSetupOpcode = -1, int CFDestroyOpcode = -1) : CallFrameSetupOpcode(CFSetupOpcode), @@ -143,9 +143,7 @@ public: /// missed. virtual bool hasLoadFromStackSlot(const MachineInstr *MI, const MachineMemOperand *&MMO, - int &FrameIndex) const { - return 0; - } + int &FrameIndex) const; /// isStoreToStackSlot - If the specified machine instruction is a direct /// store to a stack slot, return the virtual or physical register number of @@ -173,9 +171,7 @@ public: /// stack. This is just a hint, as some cases may be missed. virtual bool hasStoreToStackSlot(const MachineInstr *MI, const MachineMemOperand *&MMO, - int &FrameIndex) const { - return 0; - } + int &FrameIndex) const; /// reMaterialize - Re-issue the specified 'original' instruction at the /// specific location targeting a new destination register. @@ -186,7 +182,7 @@ public: MachineBasicBlock::iterator MI, unsigned DestReg, unsigned SubIdx, const MachineInstr *Orig, - const TargetRegisterInfo &TRI) const = 0; + const TargetRegisterInfo &TRI) const; /// duplicate - Create a duplicate of the Orig instruction in MF. This is like /// MachineFunction::CloneMachineInstr(), but the target may update operands @@ -194,7 +190,7 @@ public: /// /// The instruction must be duplicable as indicated by isNotDuplicable(). virtual MachineInstr *duplicate(MachineInstr *Orig, - MachineFunction &MF) const = 0; + MachineFunction &MF) const; /// convertToThreeAddress - This method must be implemented by targets that /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target @@ -221,13 +217,13 @@ public: /// method for a non-commutable instruction, but there may be some cases /// where this method fails and returns null. virtual MachineInstr *commuteInstruction(MachineInstr *MI, - bool NewMI = false) const = 0; + bool NewMI = false) const; /// findCommutedOpIndices - If specified MI is commutable, return the two /// operand indices that would swap value. Return false if the instruction /// is not in a form which this routine understands. virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, - unsigned &SrcOpIdx2) const = 0; + unsigned &SrcOpIdx2) const; /// produceSameValue - Return true if two machine instructions would produce /// identical values. By default, this is only true when the two instructions @@ -236,7 +232,7 @@ public: /// aggressive checks. virtual bool produceSameValue(const MachineInstr *MI0, const MachineInstr *MI1, - const MachineRegisterInfo *MRI = 0) const = 0; + const MachineRegisterInfo *MRI = 0) const; /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning /// true if it cannot be understood (e.g. it's a switch dispatch or isn't @@ -298,7 +294,7 @@ public: /// after it, replacing it with an unconditional branch to NewDest. This is /// used by the tail merging pass. virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, - MachineBasicBlock *NewDest) const = 0; + MachineBasicBlock *NewDest) const; /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic /// block at the specified instruction (i.e. instruction would be the start @@ -435,7 +431,7 @@ public: SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp, unsigned &FalseOp, bool &Optimizable) const { - assert(MI && MI->isSelect() && "MI must be a select instruction"); + assert(MI && MI->getDesc().isSelect() && "MI must be a select instruction"); return true; } @@ -569,7 +565,7 @@ public: /// folding is possible. virtual bool canFoldMemoryOperand(const MachineInstr *MI, - const SmallVectorImpl<unsigned> &Ops) const =0; + const SmallVectorImpl<unsigned> &Ops) const; /// unfoldMemoryOperand - Separate a single instruction which folded a load or /// a store or a load and a store into two or more instruction. If this is @@ -621,6 +617,26 @@ public: return false; } + /// \brief Get the base register and byte offset of a load/store instr. + virtual bool getLdStBaseRegImmOfs(MachineInstr *LdSt, + unsigned &BaseReg, unsigned &Offset, + const TargetRegisterInfo *TRI) const { + return false; + } + + virtual bool shouldClusterLoads(MachineInstr *FirstLdSt, + MachineInstr *SecondLdSt, + unsigned NumLoads) const { + return false; + } + + /// \brief Can this target fuse the given instructions if they are scheduled + /// adjacent. + virtual bool shouldScheduleAdjacent(MachineInstr* First, + MachineInstr *Second) const { + return false; + } + /// ReverseBranchCondition - Reverses the branch condition of the specified /// condition list, returning false on success and true if it cannot be /// reversed. @@ -649,13 +665,13 @@ public: /// isUnpredicatedTerminator - Returns true if the instruction is a /// terminator instruction that has not been predicated. - virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const = 0; + virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; /// PredicateInstruction - Convert the instruction into a predicated /// instruction. It returns true if the operation was successful. virtual bool PredicateInstruction(MachineInstr *MI, - const SmallVectorImpl<MachineOperand> &Pred) const = 0; + const SmallVectorImpl<MachineOperand> &Pred) const; /// SubsumesPredicate - Returns true if the first specified predicate /// subsumes the second, e.g. GE subsumes GT. @@ -691,7 +707,7 @@ public: /// terminators. virtual bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, - const MachineFunction &MF) const = 0; + const MachineFunction &MF) const; /// Measure the specified inline asm to determine an approximation of its /// length. @@ -703,21 +719,25 @@ public: /// register allocation. virtual ScheduleHazardRecognizer* CreateTargetHazardRecognizer(const TargetMachine *TM, - const ScheduleDAG *DAG) const = 0; + const ScheduleDAG *DAG) const; /// CreateTargetMIHazardRecognizer - Allocate and return a hazard recognizer /// to use for this target when scheduling the machine instructions before /// register allocation. virtual ScheduleHazardRecognizer* CreateTargetMIHazardRecognizer(const InstrItineraryData*, - const ScheduleDAG *DAG) const = 0; + const ScheduleDAG *DAG) const; /// CreateTargetPostRAHazardRecognizer - Allocate and return a hazard /// recognizer to use for this target when scheduling the machine instructions /// after register allocation. virtual ScheduleHazardRecognizer* CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, - const ScheduleDAG *DAG) const = 0; + const ScheduleDAG *DAG) const; + + /// Provide a global flag for disabling the PreRA hazard recognizer that + /// targets may choose to honor. + bool usePreRAHazardRecognizer() const; /// analyzeCompare - For a comparison instruction, return the source registers /// in SrcReg and SrcReg2 if having two register operands, and the value it @@ -765,7 +785,7 @@ public: /// IssueWidth is the number of microops that can be dispatched each /// cycle. An instruction with zero microops takes no dispatch resources. virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, - const MachineInstr *MI) const = 0; + const MachineInstr *MI) const; /// isZeroCost - Return true for pseudo instructions that don't consume any /// machine resources in their current form. These are common cases that the @@ -777,7 +797,7 @@ public: virtual int getOperandLatency(const InstrItineraryData *ItinData, SDNode *DefNode, unsigned DefIdx, - SDNode *UseNode, unsigned UseIdx) const = 0; + SDNode *UseNode, unsigned UseIdx) const; /// getOperandLatency - Compute and return the use operand latency of a given /// pair of def and use. @@ -790,7 +810,7 @@ public: virtual int getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *UseMI, - unsigned UseIdx) const = 0; + unsigned UseIdx) const; /// computeOperandLatency - Compute and return the latency of the given data /// dependent def and use when the operand indices are already known. @@ -801,29 +821,23 @@ public: const MachineInstr *UseMI, unsigned UseIdx, bool FindMin = false) const; - /// getOutputLatency - Compute and return the output dependency latency of a - /// a given pair of defs which both target the same register. This is usually - /// one. - virtual unsigned getOutputLatency(const InstrItineraryData *ItinData, - const MachineInstr *DefMI, unsigned DefIdx, - const MachineInstr *DepMI) const { - return 1; - } - /// getInstrLatency - Compute the instruction latency of a given instruction. /// If the instruction has higher cost when predicated, it's returned via /// PredCost. virtual unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr *MI, - unsigned *PredCost = 0) const = 0; + unsigned *PredCost = 0) const; virtual int getInstrLatency(const InstrItineraryData *ItinData, - SDNode *Node) const = 0; + SDNode *Node) const; /// Return the default expected latency for a def based on it's opcode. unsigned defaultDefLatency(const MCSchedModel *SchedModel, const MachineInstr *DefMI) const; + int computeDefOperandLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, bool FindMin) const; + /// isHighLatencyDef - Return true if this opcode has high latency to its /// result. virtual bool isHighLatencyDef(int opc) const { return false; } @@ -845,7 +859,7 @@ public: /// if the target considered it 'low'. virtual bool hasLowDefLatency(const InstrItineraryData *ItinData, - const MachineInstr *DefMI, unsigned DefIdx) const = 0; + const MachineInstr *DefMI, unsigned DefIdx) const; /// verifyInstruction - Perform target specific instruction verification. virtual @@ -962,84 +976,6 @@ private: int CallFrameSetupOpcode, CallFrameDestroyOpcode; }; -/// TargetInstrInfoImpl - This is the default implementation of -/// TargetInstrInfo, which just provides a couple of default implementations -/// for various methods. This separated out because it is implemented in -/// libcodegen, not in libtarget. -class TargetInstrInfoImpl : public TargetInstrInfo { -protected: - TargetInstrInfoImpl(int CallFrameSetupOpcode = -1, - int CallFrameDestroyOpcode = -1) - : TargetInstrInfo(CallFrameSetupOpcode, CallFrameDestroyOpcode) {} -public: - virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, - MachineBasicBlock *NewDest) const; - virtual MachineInstr *commuteInstruction(MachineInstr *MI, - bool NewMI = false) const; - virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, - unsigned &SrcOpIdx2) const; - virtual bool canFoldMemoryOperand(const MachineInstr *MI, - const SmallVectorImpl<unsigned> &Ops) const; - virtual bool hasLoadFromStackSlot(const MachineInstr *MI, - const MachineMemOperand *&MMO, - int &FrameIndex) const; - virtual bool hasStoreToStackSlot(const MachineInstr *MI, - const MachineMemOperand *&MMO, - int &FrameIndex) const; - virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; - virtual bool PredicateInstruction(MachineInstr *MI, - const SmallVectorImpl<MachineOperand> &Pred) const; - virtual void reMaterialize(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned DestReg, unsigned SubReg, - const MachineInstr *Orig, - const TargetRegisterInfo &TRI) const; - virtual MachineInstr *duplicate(MachineInstr *Orig, - MachineFunction &MF) const; - virtual bool produceSameValue(const MachineInstr *MI0, - const MachineInstr *MI1, - const MachineRegisterInfo *MRI) const; - virtual bool isSchedulingBoundary(const MachineInstr *MI, - const MachineBasicBlock *MBB, - const MachineFunction &MF) const; - - virtual int getOperandLatency(const InstrItineraryData *ItinData, - SDNode *DefNode, unsigned DefIdx, - SDNode *UseNode, unsigned UseIdx) const; - - virtual int getInstrLatency(const InstrItineraryData *ItinData, - SDNode *Node) const; - - virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, - const MachineInstr *MI) const; - - virtual unsigned getInstrLatency(const InstrItineraryData *ItinData, - const MachineInstr *MI, - unsigned *PredCost = 0) const; - - virtual - bool hasLowDefLatency(const InstrItineraryData *ItinData, - const MachineInstr *DefMI, unsigned DefIdx) const; - - virtual int getOperandLatency(const InstrItineraryData *ItinData, - const MachineInstr *DefMI, unsigned DefIdx, - const MachineInstr *UseMI, - unsigned UseIdx) const; - - bool usePreRAHazardRecognizer() const; - - virtual ScheduleHazardRecognizer * - CreateTargetHazardRecognizer(const TargetMachine*, const ScheduleDAG*) const; - - virtual ScheduleHazardRecognizer * - CreateTargetMIHazardRecognizer(const InstrItineraryData*, - const ScheduleDAG*) const; - - virtual ScheduleHazardRecognizer * - CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, - const ScheduleDAG*) const; -}; - } // End llvm namespace #endif diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h index c44b923..ce21349 100644 --- a/include/llvm/Target/TargetIntrinsicInfo.h +++ b/include/llvm/Target/TargetIntrinsicInfo.h @@ -14,6 +14,7 @@ #ifndef LLVM_TARGET_TARGETINTRINSICINFO_H #define LLVM_TARGET_TARGETINTRINSICINFO_H +#include "llvm/Support/Compiler.h" #include <string> namespace llvm { @@ -27,8 +28,8 @@ class Type; /// TargetIntrinsicInfo - Interface to description of machine instruction set /// class TargetIntrinsicInfo { - TargetIntrinsicInfo(const TargetIntrinsicInfo &); // DO NOT IMPLEMENT - void operator=(const TargetIntrinsicInfo &); // DO NOT IMPLEMENT + TargetIntrinsicInfo(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION; + void operator=(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION; public: TargetIntrinsicInfo(); virtual ~TargetIntrinsicInfo(); diff --git a/include/llvm/Target/TargetJITInfo.h b/include/llvm/Target/TargetJITInfo.h index 044afd9..f9bd0fb 100644 --- a/include/llvm/Target/TargetJITInfo.h +++ b/include/llvm/Target/TargetJITInfo.h @@ -17,8 +17,8 @@ #ifndef LLVM_TARGET_TARGETJITINFO_H #define LLVM_TARGET_TARGETJITINFO_H -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include <cassert> namespace llvm { diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h index 2a0a432..ceeba4f 100644 --- a/include/llvm/Target/TargetLibraryInfo.h +++ b/include/llvm/Target/TargetLibraryInfo.h @@ -10,8 +10,8 @@ #ifndef LLVM_TARGET_TARGETLIBRARYINFO_H #define LLVM_TARGET_TARGETLIBRARYINFO_H -#include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Pass.h" namespace llvm { class Triple; @@ -49,6 +49,8 @@ namespace llvm { cxa_guard_release, /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); memcpy_chk, + /// int abs(int j); + abs, /// double acos(double x); acos, /// float acosf(float x); @@ -153,6 +155,12 @@ namespace llvm { fabsf, /// long double fabsl(long double x); fabsl, + /// int ffs(int i); + ffs, + /// int ffsl(long int i); + ffsl, + /// int ffsll(long long int i); + ffsll, /// int fiprintf(FILE *stream, const char *format, ...); fiprintf, /// double floor(double x); @@ -167,6 +175,8 @@ namespace llvm { fmodf, /// long double fmodl(long double x, long double y); fmodl, + /// int fprintf(FILE *stream, const char *format, ...); + fprintf, /// int fputc(int c, FILE *stream); fputc, /// int fputs(const char *s, FILE *stream); @@ -178,6 +188,14 @@ namespace llvm { fwrite, /// int iprintf(const char *format, ...); iprintf, + /// int isascii(int c); + isascii, + /// int isdigit(int c); + isdigit, + /// long int labs(long int j); + labs, + /// long long int llabs(long long int j); + llabs, /// double log(double x); log, /// double log10(double x); @@ -236,6 +254,8 @@ namespace llvm { powf, /// long double powl(long double x, long double y); powl, + /// int printf(const char *format, ...); + printf, /// int putchar(int c); putchar, /// int puts(const char *s); @@ -270,18 +290,26 @@ namespace llvm { sinl, /// int siprintf(char *str, const char *format, ...); siprintf, + /// int sprintf(char *str, const char *format, ...); + sprintf, /// double sqrt(double x); sqrt, /// float sqrtf(float x); sqrtf, /// long double sqrtl(long double x); sqrtl, + /// char *stpcpy(char *s1, const char *s2); + stpcpy, /// char *strcat(char *s1, const char *s2); strcat, /// char *strchr(const char *s, int c); strchr, + /// int strcmp(const char *s1, const char *s2); + strcmp, /// char *strcpy(char *s1, const char *s2); strcpy, + /// size_t strcspn(const char *s1, const char *s2); + strcspn, /// char *strdup(const char *s1); strdup, /// size_t strlen(const char *s); @@ -296,6 +324,29 @@ namespace llvm { strndup, /// size_t strnlen(const char *s, size_t maxlen); strnlen, + /// char *strpbrk(const char *s1, const char *s2); + strpbrk, + /// char *strrchr(const char *s, int c); + strrchr, + /// size_t strspn(const char *s1, const char *s2); + strspn, + /// char *strstr(const char *s1, const char *s2); + strstr, + /// double strtod(const char *nptr, char **endptr); + strtod, + /// float strtof(const char *nptr, char **endptr); + strtof, + /// long int strtol(const char *nptr, char **endptr, int base); + strtol, + /// long double strtold(const char *nptr, char **endptr); + strtold, + /// long long int strtoll(const char *nptr, char **endptr, int base); + strtoll, + /// unsigned long int strtoul(const char *nptr, char **endptr, int base); + strtoul, + /// unsigned long long int strtoull(const char *nptr, char **endptr, + /// int base); + strtoull, /// double tan(double x); tan, /// float tanf(float x); @@ -308,6 +359,8 @@ namespace llvm { tanhl, /// long double tanl(long double x); tanl, + /// int toascii(int c); + toascii, /// double trunc(double x); trunc, /// float truncf(float x); diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index ef63422..eee25c9 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -22,13 +22,14 @@ #ifndef LLVM_TARGET_TARGETLOWERING_H #define LLVM_TARGET_TARGETLOWERING_H -#include "llvm/CallingConv.h" -#include "llvm/InlineAsm.h" -#include "llvm/Attributes.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/Support/CallSite.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/DAGCombine.h" #include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/DebugLoc.h" #include "llvm/Target/TargetCallingConv.h" #include "llvm/Target/TargetMachine.h" @@ -50,7 +51,7 @@ namespace llvm { class MCContext; class MCExpr; template<typename T> class SmallVectorImpl; - class TargetData; + class DataLayout; class TargetRegisterClass; class TargetLibraryInfo; class TargetLoweringObjectFile; @@ -67,7 +68,6 @@ namespace llvm { }; } - //===----------------------------------------------------------------------===// /// TargetLowering - This class defines information used to lower LLVM code to /// legal SelectionDAG operators that the target instruction selector can accept @@ -77,8 +77,8 @@ namespace llvm { /// target-specific constructs to SelectionDAG operators. /// class TargetLowering { - TargetLowering(const TargetLowering&); // DO NOT IMPLEMENT - void operator=(const TargetLowering&); // DO NOT IMPLEMENT + TargetLowering(const TargetLowering&) LLVM_DELETED_FUNCTION; + void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION; public: /// LegalizeAction - This enum indicates whether operations are valid for a /// target, and if not, what action should be used to make them valid. @@ -102,6 +102,10 @@ public: TypeWidenVector // This vector should be widened into a larger vector. }; + /// LegalizeKind holds the legalization kind that needs to happen to EVT + /// in order to type-legalize it. + typedef std::pair<LegalizeTypeAction, EVT> LegalizeKind; + enum BooleanContent { // How the target represents true/false values. UndefinedBooleanContent, // Only bit 0 counts, the rest can hold garbage. ZeroOrOneBooleanContent, // All bits zero except for bit 0. @@ -137,12 +141,15 @@ public: virtual ~TargetLowering(); const TargetMachine &getTargetMachine() const { return TM; } - const TargetData *getTargetData() const { return TD; } + const DataLayout *getDataLayout() const { return TD; } const TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; } bool isBigEndian() const { return !IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; } - MVT getPointerTy() 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 { return PointerTy; } virtual MVT getShiftAmountTy(EVT LHSTy) const; /// isSelectExpensive - Return true if the select operation is expensive for @@ -151,18 +158,23 @@ public: virtual bool isSelectSupported(SelectSupportKind kind) const { return true; } + /// shouldSplitVectorElementType - Return true if a vector of the given type + /// should be split (TypeSplitVector) instead of promoted + /// (TypePromoteInteger) during type legalization. + virtual bool shouldSplitVectorElementType(EVT VT) const { return false; } + /// isIntDivCheap() - Return true if integer divide is usually cheaper than /// a sequence of several shifts, adds, and multiplies for this target. bool isIntDivCheap() const { return IntDivIsCheap; } /// isSlowDivBypassed - Returns true if target has indicated at least one /// type should be bypassed. - bool isSlowDivBypassed() const { return !BypassSlowDivTypes.empty(); } + bool isSlowDivBypassed() const { return !BypassSlowDivWidths.empty(); } /// getBypassSlowDivTypes - Returns map of slow types for division or /// remainder with corresponding fast types - const DenseMap<Type *, Type *> &getBypassSlowDivTypes() const { - return BypassSlowDivTypes; + const DenseMap<unsigned int, unsigned int> &getBypassSlowDivWidths() const { + return BypassSlowDivWidths; } /// isPow2DivCheap() - Return true if pow2 div is cheaper than a chain of @@ -219,9 +231,8 @@ public: /// getRegClassFor - Return the register class that should be used for the /// specified value type. - virtual const TargetRegisterClass *getRegClassFor(EVT VT) const { - assert(VT.isSimple() && "getRegClassFor called on illegal type!"); - const TargetRegisterClass *RC = RegClassForVT[VT.getSimpleVT().SimpleTy]; + virtual const TargetRegisterClass *getRegClassFor(MVT VT) const { + const TargetRegisterClass *RC = RegClassForVT[VT.SimpleTy]; assert(RC && "This value type is not natively supported!"); return RC; } @@ -231,17 +242,15 @@ public: /// legal super-reg register class for the register class of the value type. /// For example, on i386 the rep register class for i8, i16, and i32 are GR32; /// while the rep register class is GR64 on x86_64. - virtual const TargetRegisterClass *getRepRegClassFor(EVT VT) const { - assert(VT.isSimple() && "getRepRegClassFor called on illegal type!"); - const TargetRegisterClass *RC = RepRegClassForVT[VT.getSimpleVT().SimpleTy]; + virtual const TargetRegisterClass *getRepRegClassFor(MVT VT) const { + const TargetRegisterClass *RC = RepRegClassForVT[VT.SimpleTy]; return RC; } /// getRepRegClassCostFor - Return the cost of the 'representative' register /// class for the specified value type. - virtual uint8_t getRepRegClassCostFor(EVT VT) const { - assert(VT.isSimple() && "getRepRegClassCostFor called on illegal type!"); - return RepRegClassCostForVT[VT.getSimpleVT().SimpleTy]; + virtual uint8_t getRepRegClassCostFor(MVT VT) const { + return RepRegClassCostForVT[VT.SimpleTy]; } /// isTypeLegal - Return true if the target has native support for the @@ -267,8 +276,8 @@ public: return (LegalizeTypeAction)ValueTypeActions[VT.SimpleTy]; } - void setTypeAction(EVT VT, LegalizeTypeAction Action) { - unsigned I = VT.getSimpleVT().SimpleTy; + void setTypeAction(MVT VT, LegalizeTypeAction Action) { + unsigned I = VT.SimpleTy; ValueTypeActions[I] = Action; } }; @@ -329,7 +338,7 @@ public: unsigned getVectorTypeBreakdown(LLVMContext &Context, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, - EVT &RegisterVT) const; + MVT &RegisterVT) const; /// getTgtMemIntrinsic: Given an intrinsic, checks if on the target the /// intrinsic will need to map to a MemIntrinsicNode (touches memory). If @@ -403,6 +412,22 @@ public: getOperationAction(Op, VT) == Custom); } + /// isOperationLegalOrPromote - Return true if the specified operation is + /// legal on this target or can be made legal using promotion. This + /// is used to help guide high-level lowering decisions. + bool isOperationLegalOrPromote(unsigned Op, EVT VT) const { + return (VT == MVT::Other || isTypeLegal(VT)) && + (getOperationAction(Op, VT) == Legal || + getOperationAction(Op, VT) == Promote); + } + + /// isOperationExpand - Return true if the specified operation is illegal on + /// this target or unlikely to be made legal with custom lowering. This is + /// used to help guide high-level lowering decisions. + bool isOperationExpand(unsigned Op, EVT VT) const { + return (!isTypeLegal(VT) || getOperationAction(Op, VT) == Expand); + } + /// isOperationLegal - Return true if the specified operation is legal on this /// target. bool isOperationLegal(unsigned Op, EVT VT) const { @@ -414,36 +439,35 @@ public: /// either it is legal, needs to be promoted to a larger size, needs to be /// expanded to some other code sequence, or the target has a custom expander /// for it. - LegalizeAction getLoadExtAction(unsigned ExtType, EVT VT) const { - assert(ExtType < ISD::LAST_LOADEXT_TYPE && - VT.getSimpleVT() < MVT::LAST_VALUETYPE && + LegalizeAction getLoadExtAction(unsigned ExtType, MVT VT) const { + assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)LoadExtActions[VT.getSimpleVT().SimpleTy][ExtType]; + return (LegalizeAction)LoadExtActions[VT.SimpleTy][ExtType]; } /// isLoadExtLegal - Return true if the specified load with extension is legal /// on this target. bool isLoadExtLegal(unsigned ExtType, EVT VT) const { - return VT.isSimple() && getLoadExtAction(ExtType, VT) == Legal; + return VT.isSimple() && + getLoadExtAction(ExtType, VT.getSimpleVT()) == Legal; } /// getTruncStoreAction - Return how this store with truncation should be /// treated: either it is legal, needs to be promoted to a larger size, needs /// to be expanded to some other code sequence, or the target has a custom /// expander for it. - LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const { - assert(ValVT.getSimpleVT() < MVT::LAST_VALUETYPE && - MemVT.getSimpleVT() < MVT::LAST_VALUETYPE && + LegalizeAction getTruncStoreAction(MVT ValVT, MVT MemVT) const { + assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)TruncStoreActions[ValVT.getSimpleVT().SimpleTy] - [MemVT.getSimpleVT().SimpleTy]; + return (LegalizeAction)TruncStoreActions[ValVT.SimpleTy] + [MemVT.SimpleTy]; } /// isTruncStoreLegal - Return true if the specified store with truncation is /// legal on this target. bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const { return isTypeLegal(ValVT) && MemVT.isSimple() && - getTruncStoreAction(ValVT, MemVT) == Legal; + getTruncStoreAction(ValVT.getSimpleVT(), MemVT.getSimpleVT()) == Legal; } /// getIndexedLoadAction - Return how the indexed load should be treated: @@ -451,11 +475,10 @@ public: /// expanded to some other code sequence, or the target has a custom expander /// for it. LegalizeAction - getIndexedLoadAction(unsigned IdxMode, EVT VT) const { - assert(IdxMode < ISD::LAST_INDEXED_MODE && - VT.getSimpleVT() < MVT::LAST_VALUETYPE && + getIndexedLoadAction(unsigned IdxMode, MVT VT) const { + assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - unsigned Ty = (unsigned)VT.getSimpleVT().SimpleTy; + unsigned Ty = (unsigned)VT.SimpleTy; return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] & 0xf0) >> 4); } @@ -463,8 +486,8 @@ public: /// on this target. bool isIndexedLoadLegal(unsigned IdxMode, EVT VT) const { return VT.isSimple() && - (getIndexedLoadAction(IdxMode, VT) == Legal || - getIndexedLoadAction(IdxMode, VT) == Custom); + (getIndexedLoadAction(IdxMode, VT.getSimpleVT()) == Legal || + getIndexedLoadAction(IdxMode, VT.getSimpleVT()) == Custom); } /// getIndexedStoreAction - Return how the indexed store should be treated: @@ -472,11 +495,10 @@ public: /// expanded to some other code sequence, or the target has a custom expander /// for it. LegalizeAction - getIndexedStoreAction(unsigned IdxMode, EVT VT) const { - assert(IdxMode < ISD::LAST_INDEXED_MODE && - VT.getSimpleVT() < MVT::LAST_VALUETYPE && + getIndexedStoreAction(unsigned IdxMode, MVT VT) const { + assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - unsigned Ty = (unsigned)VT.getSimpleVT().SimpleTy; + unsigned Ty = (unsigned)VT.SimpleTy; return (LegalizeAction)(IndexedModeActions[Ty][IdxMode] & 0x0f); } @@ -484,50 +506,54 @@ public: /// on this target. bool isIndexedStoreLegal(unsigned IdxMode, EVT VT) const { return VT.isSimple() && - (getIndexedStoreAction(IdxMode, VT) == Legal || - getIndexedStoreAction(IdxMode, VT) == Custom); + (getIndexedStoreAction(IdxMode, VT.getSimpleVT()) == Legal || + getIndexedStoreAction(IdxMode, VT.getSimpleVT()) == Custom); } /// getCondCodeAction - Return how the condition code should be treated: /// either it is legal, needs to be expanded to some other code sequence, /// or the target has a custom expander for it. LegalizeAction - getCondCodeAction(ISD::CondCode CC, EVT VT) const { + getCondCodeAction(ISD::CondCode CC, MVT VT) const { assert((unsigned)CC < array_lengthof(CondCodeActions) && - (unsigned)VT.getSimpleVT().SimpleTy < sizeof(CondCodeActions[0])*4 && + (unsigned)VT.SimpleTy < sizeof(CondCodeActions[0])*4 && "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] >> (2*VT.getSimpleVT().SimpleTy)) & 3); + ((CondCodeActions[CC][VT.SimpleTy >> 5] >> (2*(VT.SimpleTy & 0x1F))) & 3); assert(Action != Promote && "Can't promote condition code!"); return Action; } /// isCondCodeLegal - Return true if the specified condition code is legal /// on this target. - bool isCondCodeLegal(ISD::CondCode CC, EVT VT) const { - return getCondCodeAction(CC, VT) == Legal || - getCondCodeAction(CC, VT) == Custom; + bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const { + return + getCondCodeAction(CC, VT) == Legal || + getCondCodeAction(CC, VT) == Custom; } /// getTypeToPromoteTo - If the action for this operation is to promote, this /// method returns the ValueType to promote to. - EVT getTypeToPromoteTo(unsigned Op, EVT VT) const { + MVT getTypeToPromoteTo(unsigned Op, MVT VT) const { assert(getOperationAction(Op, VT) == Promote && "This operation isn't promoted!"); // See if this has an explicit type specified. std::map<std::pair<unsigned, MVT::SimpleValueType>, MVT::SimpleValueType>::const_iterator PTTI = - PromoteToType.find(std::make_pair(Op, VT.getSimpleVT().SimpleTy)); + PromoteToType.find(std::make_pair(Op, VT.SimpleTy)); if (PTTI != PromoteToType.end()) return PTTI->second; assert((VT.isInteger() || VT.isFloatingPoint()) && "Cannot autopromote this type, add it with AddPromotedToType."); - EVT NVT = VT; + MVT NVT = VT; do { - NVT = (MVT::SimpleValueType)(NVT.getSimpleVT().SimpleTy+1); + NVT = (MVT::SimpleValueType)(NVT.SimpleTy+1); assert(NVT.isInteger() == VT.isInteger() && NVT != MVT::isVoid && "Didn't find type to promote to!"); } while (!isTypeLegal(NVT) || @@ -555,6 +581,11 @@ public: return EVT::getEVT(Ty, AllowUnknown); } + /// Return the MVT corresponding to this LLVM type. See getValueType. + MVT getSimpleValueType(Type *Ty, bool AllowUnknown = false) const { + return getValueType(Ty, AllowUnknown).getSimpleVT(); + } + /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate /// function arguments in the caller parameter area. This is the actual /// alignment, not its logarithm. @@ -562,21 +593,22 @@ public: /// getRegisterType - Return the type of registers that this ValueType will /// eventually require. - EVT getRegisterType(MVT VT) const { + MVT getRegisterType(MVT VT) const { assert((unsigned)VT.SimpleTy < array_lengthof(RegisterTypeForVT)); return RegisterTypeForVT[VT.SimpleTy]; } /// getRegisterType - Return the type of registers that this ValueType will /// eventually require. - EVT getRegisterType(LLVMContext &Context, EVT VT) const { + MVT getRegisterType(LLVMContext &Context, EVT VT) const { if (VT.isSimple()) { assert((unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegisterTypeForVT)); return RegisterTypeForVT[VT.getSimpleVT().SimpleTy]; } if (VT.isVector()) { - EVT VT1, RegisterVT; + EVT VT1; + MVT RegisterVT; unsigned NumIntermediates; (void)getVectorTypeBreakdown(Context, VT, VT1, NumIntermediates, RegisterVT); @@ -601,7 +633,8 @@ public: return NumRegistersForVT[VT.getSimpleVT().SimpleTy]; } if (VT.isVector()) { - EVT VT1, VT2; + EVT VT1; + MVT VT2; unsigned NumIntermediates; return getVectorTypeBreakdown(Context, VT, VT1, NumIntermediates, VT2); } @@ -653,12 +686,14 @@ public: } /// This function returns true if the target allows unaligned memory accesses. - /// of the specified type. This is used, for example, in situations where an - /// array copy/move/set is converted to a sequence of store operations. It's - /// use helps to ensure that such replacements don't generate code that causes - /// an alignment error (trap) on the target machine. + /// of the specified type. If true, it also returns whether the unaligned + /// memory access is "fast" in the second argument by reference. This is used, + /// for example, in situations where an array copy/move/set is converted to a + /// sequence of store operations. It's use helps to ensure that such + /// replacements don't generate code that causes an alignment error (trap) on + /// the target machine. /// @brief Determine if the target supports unaligned memory accesses. - virtual bool allowsUnalignedMemoryAccesses(EVT) const { + virtual bool allowsUnalignedMemoryAccesses(EVT, bool *Fast = 0) const { return false; } @@ -674,21 +709,31 @@ public: /// lowering. If DstAlign is zero that means it's safe to destination /// alignment can satisfy any constraint. Similarly if SrcAlign is zero it /// means there isn't a need to check it against alignment requirement, - /// probably because the source does not need to be loaded. If - /// 'IsZeroVal' is true, that means it's safe to return a - /// non-scalar-integer type, e.g. empty string source, constant, or loaded - /// from memory. 'MemcpyStrSrc' indicates whether the memcpy source is - /// constant so it does not need to be loaded. + /// probably because the source does not need to be loaded. If 'IsMemset' is + /// true, that means it's expanding a memset. If 'ZeroMemset' is true, that + /// means it's a memset of zero. 'MemcpyStrSrc' indicates whether the memcpy + /// source is constant so it does not need to be loaded. /// It returns EVT::Other if the type should be determined using generic /// target-independent logic. virtual EVT getOptimalMemOpType(uint64_t /*Size*/, unsigned /*DstAlign*/, unsigned /*SrcAlign*/, - bool /*IsZeroVal*/, + bool /*IsMemset*/, + bool /*ZeroMemset*/, bool /*MemcpyStrSrc*/, MachineFunction &/*MF*/) const { return MVT::Other; } + /// isSafeMemOpType - Returns true if it's safe to use load / store of the + /// specified type to expand memcpy / memset inline. This is mostly true + /// for all types except for some special cases. For example, on X86 + /// targets without SSE2 f64 load / store are done with fldl / fstpl which + /// also does type conversion. Note the specified type doesn't have to be + /// legal as the hook is used before type legalization. + virtual bool isSafeMemOpType(MVT VT) const { + return true; + } + /// usesUnderscoreSetJmp - Determine if we should use _setjmp or setjmp /// to implement llvm.setjmp. bool usesUnderscoreSetJmp() const { @@ -707,6 +752,12 @@ public: return SupportJumpTables; } + /// getMinimumJumpTableEntries - return integer threshold on number of + /// blocks to use jump tables rather than if sequence. + int getMinimumJumpTableEntries() const { + return MinimumJumpTableEntries; + } + /// getStackPointerRegisterToSaveRestore - If a physical register, this /// specifies the register that llvm.savestack/llvm.restorestack should save /// and restore. @@ -843,6 +894,18 @@ public: } //===--------------------------------------------------------------------===// + /// \name Helpers for TargetTransformInfo implementations + /// @{ + + /// Get the ISD node that corresponds to the Instruction class opcode. + int InstructionOpcodeToISD(unsigned Opcode) const; + + /// Estimate the cost of type-legalization and the legalized type. + std::pair<unsigned, MVT> getTypeLegalizationCost(Type *Ty) const; + + /// @} + + //===--------------------------------------------------------------------===// // TargetLowering Optimization Methods // @@ -912,18 +975,20 @@ public: struct DAGCombinerInfo { void *DC; // The DAG Combiner object. - bool BeforeLegalize; - bool BeforeLegalizeOps; + CombineLevel Level; bool CalledByLegalizer; public: SelectionDAG &DAG; - DAGCombinerInfo(SelectionDAG &dag, bool bl, bool blo, bool cl, void *dc) - : DC(dc), BeforeLegalize(bl), BeforeLegalizeOps(blo), - CalledByLegalizer(cl), DAG(dag) {} + DAGCombinerInfo(SelectionDAG &dag, CombineLevel level, bool cl, void *dc) + : DC(dc), Level(level), CalledByLegalizer(cl), DAG(dag) {} - bool isBeforeLegalize() const { return BeforeLegalize; } - bool isBeforeLegalizeOps() const { return BeforeLegalizeOps; } + bool isBeforeLegalize() const { return Level == BeforeLegalizeTypes; } + bool isBeforeLegalizeOps() const { return Level < AfterLegalizeVectorOps; } + bool isAfterLegalizeVectorOps() const { + return Level == AfterLegalizeDAG; + } + CombineLevel getDAGCombineLevel() { return Level; } bool isCalledByLegalizer() const { return CalledByLegalizer; } void AddToWorklist(SDNode *N); @@ -1027,6 +1092,12 @@ protected: SupportJumpTables = Val; } + /// setMinimumJumpTableEntries - Indicate the number of blocks to generate + /// jump tables rather than if sequence. + void setMinimumJumpTableEntries(int Val) { + MinimumJumpTableEntries = Val; + } + /// setStackPointerRegisterToSaveRestore - If set to a physical register, this /// specifies the register that llvm.savestack/llvm.restorestack should save /// and restore. @@ -1066,9 +1137,9 @@ protected: /// of instructions not containing an integer divide. void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; } - /// addBypassSlowDivType - Tells the code generator which types to bypass. - void addBypassSlowDivType(Type *slow_type, Type *fast_type) { - BypassSlowDivTypes[slow_type] = fast_type; + /// addBypassSlowDiv - Tells the code generator which bitwidths to bypass. + void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth) { + BypassSlowDivWidths[SlowBitWidth] = FastBitWidth; } /// setPow2DivIsCheap - Tells the code generator that it shouldn't generate @@ -1079,16 +1150,16 @@ protected: /// addRegisterClass - Add the specified register class as an available /// regclass for the specified value type. This indicates the selector can /// handle values of that class natively. - void addRegisterClass(EVT VT, const TargetRegisterClass *RC) { - assert((unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); + void addRegisterClass(MVT VT, const TargetRegisterClass *RC) { + assert((unsigned)VT.SimpleTy < array_lengthof(RegClassForVT)); AvailableRegClasses.push_back(std::make_pair(VT, RC)); - RegClassForVT[VT.getSimpleVT().SimpleTy] = RC; + RegClassForVT[VT.SimpleTy] = RC; } /// findRepresentativeClass - Return the largest legal super-reg register class /// of the register class for the specified type and its associated "cost". virtual std::pair<const TargetRegisterClass*, uint8_t> - findRepresentativeClass(EVT VT) const; + findRepresentativeClass(MVT VT) const; /// computeRegisterProperties - Once all of the register classes are added, /// this allows us to compute derived properties we expose. @@ -1153,8 +1224,13 @@ protected: assert(VT < MVT::LAST_VALUETYPE && (unsigned)CC < array_lengthof(CondCodeActions) && "Table isn't big enough!"); - CondCodeActions[(unsigned)CC] &= ~(uint64_t(3UL) << VT.SimpleTy*2); - CondCodeActions[(unsigned)CC] |= (uint64_t)Action << VT.SimpleTy*2; + /// 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; } /// AddPromotedToType - If Opc/OrigVT is specified as being promoted, the @@ -1227,7 +1303,7 @@ protected: public: //===--------------------------------------------------------------------===// // Lowering methods - These methods must be implemented by targets so that - // the SelectionDAGLowering code knows how to lower these. + // the SelectionDAGBuilder code knows how to lower these. // /// LowerFormalArguments - This hook must be implemented to lower the @@ -1340,7 +1416,7 @@ public: } /// HandleByVal - Target-specific cleanup for formal ByVal parameters. - virtual void HandleByVal(CCState *, unsigned &) const {} + virtual void HandleByVal(CCState *, unsigned &, unsigned) const {} /// CanLowerReturn - This hook should be implemented to check whether the /// return values described by the Outs array can fit into the return @@ -1392,9 +1468,9 @@ public: /// but this is not true all the time, e.g. i1 on x86-64. It is also not /// necessary for non-C calling conventions. The frontend should handle this /// and include all of the necessary information. - virtual EVT getTypeForExtArgOrReturn(LLVMContext &Context, EVT VT, + virtual MVT getTypeForExtArgOrReturn(MVT VT, ISD::NodeType /*ExtendKind*/) const { - EVT MinVT = getRegisterType(Context, MVT::i32); + MVT MinVT = getRegisterType(MVT::i32); return VT.bitsLT(MinVT) ? MinVT : VT; } @@ -1501,7 +1577,7 @@ public: Value *CallOperandVal; /// ConstraintVT - The ValueType for the operand value. - EVT ConstraintVT; + MVT ConstraintVT; /// isMatchingInputConstraint - Return true of this is an input operand that /// is a matching constraint like "4". @@ -1610,6 +1686,17 @@ public: // Addressing mode description hooks (used by LSR etc). // + /// GetAddrModeArguments - CodeGenPrepare sinks address calculations into the + /// same BB as Load/Store instructions reading the address. This allows as + /// much computation as possible to be done in the address mode for that + /// operand. This hook lets targets also pass back when this should be done + /// on intrinsics which load/store. + virtual bool GetAddrModeArguments(IntrinsicInst *I, + SmallVectorImpl<Value*> &Ops, + Type *&AccessTy) const { + return false; + } + /// AddrMode - This represents an addressing mode of: /// BaseGV + BaseOffs + BaseReg + Scale*ScaleReg /// If BaseGV is null, there is no BaseGV. @@ -1626,17 +1713,6 @@ public: AddrMode() : BaseGV(0), BaseOffs(0), HasBaseReg(false), Scale(0) {} }; - /// GetAddrModeArguments - CodeGenPrepare sinks address calculations into the - /// same BB as Load/Store instructions reading the address. This allows as - /// much computation as possible to be done in the address mode for that - /// operand. This hook lets targets also pass back when this should be done - /// on intrinsics which load/store. - virtual bool GetAddrModeArguments(IntrinsicInst *I, - SmallVectorImpl<Value*> &Ops, - Type *&AccessTy) const { - return false; - } - /// isLegalAddressingMode - Return true if the addressing mode represented by /// AM is legal for this target, for a load/store of the specified type. /// The type may be VoidTy, in which case only return true if the addressing @@ -1687,6 +1763,13 @@ public: return false; } + /// isZExtFree - 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). + virtual bool isZExtFree(SDValue Val, EVT VT2) const { + return isZExtFree(Val.getValueType(), VT2); + } + /// isFNegFree - Return true if an fneg operation is free to the point where /// it is never worthwhile to replace it with a bitwise operation. virtual bool isFNegFree(EVT) const { @@ -1720,9 +1803,9 @@ public: SDValue BuildExactSDIV(SDValue Op1, SDValue Op2, DebugLoc dl, SelectionDAG &DAG) const; SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, - std::vector<SDNode*>* Created) const; + std::vector<SDNode*> *Created) const; SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, - std::vector<SDNode*>* Created) const; + std::vector<SDNode*> *Created) const; //===--------------------------------------------------------------------===// @@ -1767,10 +1850,11 @@ public: private: const TargetMachine &TM; - const TargetData *TD; + const DataLayout *TD; const TargetLoweringObjectFile &TLOF; - /// PointerTy - The type to use for pointers, usually i32 or i64. + /// PointerTy - The type to use for pointers for the default address space, + /// usually i32 or i64. /// MVT PointerTy; @@ -1788,11 +1872,11 @@ private: /// set to true unconditionally. bool IntDivIsCheap; - /// BypassSlowDivTypes - Tells the code generator to bypass slow divide or - /// remainder instructions. For example, SlowDivBypass[i32,u8] tells the code - /// generator to bypass 32-bit signed integer div/rem with an 8-bit unsigned + /// BypassSlowDivMap - Tells the code generator to bypass slow divide or + /// remainder instructions. For example, BypassSlowDivWidths[32,8] tells the + /// code generator to bypass 32-bit integer div/rem with an 8-bit unsigned /// integer div/rem when the operands are positive and less than 256. - DenseMap <Type *, Type *> BypassSlowDivTypes; + DenseMap <unsigned int, unsigned int> BypassSlowDivWidths; /// Pow2DivIsCheap - Tells the code generator that it shouldn't generate /// srl/add/sra for a signed divide by power of two, and let the target handle @@ -1816,6 +1900,9 @@ private: /// If it's not true, then each jumptable must be lowered into if-then-else's. bool SupportJumpTables; + /// MinimumJumpTableEntries - Number of blocks threshold to use jump tables. + int MinimumJumpTableEntries; + /// BooleanContents - Information about the contents of the high-bits in /// boolean values held in a type wider than i1. See getBooleanContents. BooleanContent BooleanContents; @@ -1884,7 +1971,7 @@ private: /// each ValueType the target supports natively. const TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE]; unsigned char NumRegistersForVT[MVT::LAST_VALUETYPE]; - EVT RegisterTypeForVT[MVT::LAST_VALUETYPE]; + MVT RegisterTypeForVT[MVT::LAST_VALUETYPE]; /// RepRegClassForVT - This indicates the "representative" register class to /// use for each ValueType the target supports natively. This information is @@ -1904,7 +1991,7 @@ private: /// contains one step of the expand (e.g. i64 -> i32), even if there are /// multiple steps required (e.g. i64 -> i16). For types natively supported /// by the system, this holds the same type (e.g. i32 -> i32). - EVT TransformToType[MVT::LAST_VALUETYPE]; + MVT TransformToType[MVT::LAST_VALUETYPE]; /// OpActions - For each operation and each value type, keep a LegalizeAction /// that indicates how instruction selection should deal with the operation. @@ -1933,26 +2020,34 @@ private: /// CondCodeActions - For each condition code (ISD::CondCode) keep a /// LegalizeAction that indicates how instruction selection should /// deal with the condition code. - uint64_t CondCodeActions[ISD::SETCC_INVALID]; + /// 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]; ValueTypeActionImpl ValueTypeActions; - typedef std::pair<LegalizeTypeAction, EVT> LegalizeKind; - +public: LegalizeKind getTypeConversion(LLVMContext &Context, EVT VT) const { // If this is a simple type, use the ComputeRegisterProp mechanism. if (VT.isSimple()) { - assert((unsigned)VT.getSimpleVT().SimpleTy < - array_lengthof(TransformToType)); - EVT NVT = TransformToType[VT.getSimpleVT().SimpleTy]; - LegalizeTypeAction LA = ValueTypeActions.getTypeAction(VT.getSimpleVT()); + MVT SVT = VT.getSimpleVT(); + assert((unsigned)SVT.SimpleTy < array_lengthof(TransformToType)); + MVT NVT = TransformToType[SVT.SimpleTy]; + LegalizeTypeAction LA = ValueTypeActions.getTypeAction(SVT); assert( - (!(NVT.isSimple() && LA != TypeLegal) || - ValueTypeActions.getTypeAction(NVT.getSimpleVT()) != TypePromoteInteger) + (LA == TypeLegal || + ValueTypeActions.getTypeAction(NVT) != TypePromoteInteger) && "Promote may not follow Expand or Promote"); + if (LA == TypeSplitVector) + return LegalizeKind(LA, EVT::getVectorVT(Context, + SVT.getVectorElementType(), + SVT.getVectorNumElements()/2)); + if (LA == TypeScalarizeVector) + return LegalizeKind(LA, SVT.getVectorElementType()); return LegalizeKind(LA, NVT); } @@ -2055,7 +2150,8 @@ private: return LegalizeKind(TypeSplitVector, NVT); } - std::vector<std::pair<EVT, const TargetRegisterClass*> > AvailableRegClasses; +private: + std::vector<std::pair<MVT, const TargetRegisterClass*> > AvailableRegClasses; /// TargetDAGCombineArray - Targets can specify ISD nodes that they would /// like PerformDAGCombine callbacks for by calling setTargetDAGCombine(), @@ -2148,7 +2244,7 @@ private: /// GetReturnInfo - Given an LLVM IR type and return type attributes, /// compute the return value EVTs and flags, and optionally also /// the offsets, if the return value is being lowered to memory. -void GetReturnInfo(Type* ReturnType, Attributes attr, +void GetReturnInfo(Type* ReturnType, AttributeSet attr, SmallVectorImpl<ISD::OutputArg> &Outs, const TargetLowering &TLI); diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index d631f58..9958755 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -15,10 +15,10 @@ #ifndef LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H #define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H -#include "llvm/Module.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/SectionKind.h" -#include "llvm/ADT/ArrayRef.h" namespace llvm { class MachineModuleInfo; @@ -27,16 +27,18 @@ namespace llvm { class MCExpr; class MCSection; class MCSymbol; + class MCSymbolRefExpr; class MCStreamer; class GlobalValue; class TargetMachine; class TargetLoweringObjectFile : public MCObjectFileInfo { MCContext *Ctx; - - TargetLoweringObjectFile(const TargetLoweringObjectFile&); // DO NOT IMPLEMENT - void operator=(const TargetLoweringObjectFile&); // DO NOT IMPLEMENT - + + TargetLoweringObjectFile( + const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION; + void operator=(const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION; + public: MCContext &getContext() const { return *Ctx; } @@ -107,13 +109,13 @@ public: return 0; } - /// getExprForDwarfGlobalReference - Return an MCExpr to use for a reference + /// getTTypeGlobalReference - Return an MCExpr to use for a reference /// to the specified global variable from exception handling information. /// virtual const MCExpr * - getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding, - MCStreamer &Streamer) const; + getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding, + MCStreamer &Streamer) const; // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. virtual MCSymbol * @@ -122,8 +124,8 @@ public: /// const MCExpr * - getExprForDwarfReference(const MCSymbol *Sym, unsigned Encoding, - MCStreamer &Streamer) const; + getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding, + MCStreamer &Streamer) const; virtual const MCSection * getStaticCtorSection(unsigned Priority = 65535) const { diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index e4bf32b..aa049f0 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -14,10 +14,10 @@ #ifndef LLVM_TARGET_TARGETMACHINE_H #define LLVM_TARGET_TARGETMACHINE_H +#include "llvm/ADT/StringRef.h" #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/StringRef.h" #include <cassert> #include <string> @@ -31,8 +31,7 @@ class MCCodeGenInfo; class MCContext; class PassManagerBase; class Target; -class TargetData; -class TargetELFWriterInfo; +class DataLayout; class TargetFrameLowering; class TargetInstrInfo; class TargetIntrinsicInfo; @@ -42,6 +41,8 @@ class TargetPassConfig; class TargetRegisterInfo; class TargetSelectionDAGInfo; class TargetSubtargetInfo; +class ScalarTargetTransformInfo; +class VectorTargetTransformInfo; class formatted_raw_ostream; class raw_ostream; @@ -52,8 +53,8 @@ class raw_ostream; /// through this interface. /// class TargetMachine { - TargetMachine(const TargetMachine &); // DO NOT IMPLEMENT - void operator=(const TargetMachine &); // DO NOT IMPLEMENT + TargetMachine(const TargetMachine &) LLVM_DELETED_FUNCTION; + void operator=(const TargetMachine &) LLVM_DELETED_FUNCTION; protected: // Can only create subclasses. TargetMachine(const Target &T, StringRef TargetTriple, StringRef CPU, StringRef FS, const TargetOptions &Options); @@ -106,7 +107,7 @@ public: virtual const TargetFrameLowering *getFrameLowering() const { return 0; } virtual const TargetLowering *getTargetLowering() const { return 0; } virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const{ return 0; } - virtual const TargetData *getTargetData() const { return 0; } + virtual const DataLayout *getDataLayout() const { return 0; } /// getMCAsmInfo - Return target specific asm information. /// @@ -142,11 +143,6 @@ public: return 0; } - /// getELFWriterInfo - If this target supports an ELF writer, return - /// information for it, otherwise return null. - /// - virtual const TargetELFWriterInfo *getELFWriterInfo() const { return 0; } - /// hasMCRelaxAll - Check whether all machine code instructions should be /// relaxed. bool hasMCRelaxAll() const { return MCRelaxAll; } @@ -232,6 +228,9 @@ public: /// sections. static void setFunctionSections(bool); + /// \brief Register analysis passes for this target with a pass manager. + virtual void addAnalysisPasses(PassManagerBase &) {} + /// CodeGenFileType - These enums are meant to be passed into /// addPassesToEmitFile to indicate what type of file to emit, and returned by /// it to indicate what type of file could actually be made. @@ -290,6 +289,11 @@ protected: // Can only create subclasses. CodeGenOpt::Level OL); public: + /// \brief Register analysis passes for this target with a pass manager. + /// + /// This registers target independent analysis passes. + virtual void addAnalysisPasses(PassManagerBase &PM); + /// createPassConfig - Create a pass configuration object to be used by /// addPassToEmitX methods for generating a pipeline of CodeGen passes. virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 68ca567..8fc566e 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -24,7 +24,7 @@ namespace llvm { // Possible float ABI settings. Used with FloatABIType in TargetOptions.h. namespace FloatABI { enum ABIType { - Default, // Target-specific (either soft or hard depending on triple, etc). + Default, // Target-specific (either soft or hard depending on triple,etc). Soft, // Soft float. Hard // Hard float. }; @@ -50,7 +50,7 @@ namespace llvm { GuaranteedTailCallOpt(false), DisableTailCalls(false), StackAlignmentOverride(0), RealignStack(true), EnableFastISel(false), PositionIndependentExecutable(false), EnableSegmentedStacks(false), - UseInitArray(false), TrapFuncName(""), FloatABIType(FloatABI::Default), + UseInitArray(false), TrapFuncName(""),FloatABIType(FloatABI::Default), AllowFPOpFusion(FPOpFusion::Standard) {} @@ -202,10 +202,10 @@ namespace llvm { /// Strict mode - allow fusion only if/when it can be proven that the excess /// precision won't effect the result. /// - /// Note: This option only controls formation of fused ops by the optimizers. - /// Fused operations that are explicitly specified (e.g. FMA via the - /// llvm.fma.* intrinsic) will always be honored, regardless of the value of - /// this option. + /// Note: This option only controls formation of fused ops by the + /// optimizers. Fused operations that are explicitly specified (e.g. FMA + /// via the llvm.fma.* intrinsic) will always be honored, regardless of + /// the value of this option. FPOpFusion::FPOpFusionMode AllowFPOpFusion; }; diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index df4d900..2a8ef98 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -16,11 +16,11 @@ #ifndef LLVM_TARGET_TARGETREGISTERINFO_H #define LLVM_TARGET_TARGETREGISTERINFO_H -#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ValueTypes.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/CallingConv.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/MC/MCRegisterInfo.h" #include <cassert> #include <functional> @@ -30,12 +30,13 @@ class BitVector; class MachineFunction; class RegScavenger; template<class T> class SmallVectorImpl; +class VirtRegMap; class raw_ostream; class TargetRegisterClass { public: - typedef const uint16_t* iterator; - typedef const uint16_t* const_iterator; + typedef const MCPhysReg* iterator; + typedef const MCPhysReg* const_iterator; typedef const MVT::SimpleValueType* vt_iterator; typedef const TargetRegisterClass* const * sc_iterator; @@ -45,7 +46,7 @@ public: const uint32_t *SubClassMask; const uint16_t *SuperRegIndices; const sc_iterator SuperClasses; - ArrayRef<uint16_t> (*OrderFunc)(const MachineFunction&); + ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&); /// getID() - Return the register class ID number. /// @@ -190,7 +191,7 @@ public: /// /// By default, this method returns all registers in the class. /// - ArrayRef<uint16_t> getRawAllocationOrder(const MachineFunction &MF) const { + ArrayRef<MCPhysReg> getRawAllocationOrder(const MachineFunction &MF) const { return OrderFunc ? OrderFunc(MF) : makeArrayRef(begin(), getNumRegs()); } }; @@ -221,13 +222,17 @@ public: private: const TargetRegisterInfoDesc *InfoDesc; // Extra desc array for codegen const char *const *SubRegIndexNames; // Names of subreg indexes. + // Pointer to array of lane masks, one per sub-reg index. + const unsigned *SubRegIndexLaneMasks; + regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses protected: TargetRegisterInfo(const TargetRegisterInfoDesc *ID, regclass_iterator RegClassBegin, regclass_iterator RegClassEnd, - const char *const *subregindexnames); + const char *const *SRINames, + const unsigned *SRILaneMasks); virtual ~TargetRegisterInfo(); public: @@ -327,10 +332,36 @@ public: /// getSubRegIndexName - Return the human-readable symbolic target-specific /// name for the specified SubRegIndex. const char *getSubRegIndexName(unsigned SubIdx) const { - assert(SubIdx && "This is not a subregister index"); + assert(SubIdx && SubIdx < getNumSubRegIndices() && + "This is not a subregister index"); return SubRegIndexNames[SubIdx-1]; } + /// getSubRegIndexLaneMask - Return a bitmask representing the parts of a + /// register that are covered by SubIdx. + /// + /// Lane masks for sub-register indices are similar to register units for + /// physical registers. The individual bits in a lane mask can't be assigned + /// any specific meaning. They can be used to check if two sub-register + /// indices overlap. + /// + /// If the target has a register such that: + /// + /// getSubReg(Reg, A) overlaps getSubReg(Reg, B) + /// + /// then: + /// + /// getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B) != 0 + /// + /// The converse is not necessarily true. If two lane masks have a common + /// bit, the corresponding sub-registers may not overlap, but it can be + /// assumed that they usually will. + unsigned getSubRegIndexLaneMask(unsigned SubIdx) const { + // SubIdx == 0 is allowed, it has the lane mask ~0u. + assert(SubIdx < getNumSubRegIndices() && "This is not a subregister index"); + return SubRegIndexLaneMasks[SubIdx]; + } + /// regsOverlap - Returns true if the two registers are equal or alias each /// other. The registers may be virtual register. bool regsOverlap(unsigned regA, unsigned regB) const { @@ -357,27 +388,12 @@ public: return false; } - /// isSubRegister - Returns true if regB is a sub-register of regA. - /// - bool isSubRegister(unsigned regA, unsigned regB) const { - return isSuperRegister(regB, regA); - } - - /// isSuperRegister - Returns true if regB is a super-register of regA. - /// - bool isSuperRegister(unsigned RegA, unsigned RegB) const { - for (MCSuperRegIterator I(RegA, this); I.isValid(); ++I) - if (*I == RegB) - return true; - return false; - } - /// getCalleeSavedRegs - Return a null-terminated list of all of the /// callee saved registers on this target. The register should be in the /// order of desired callee-save stack frame offset. The first register is /// closest to the incoming stack pointer if stack grows down, and vice versa. /// - virtual const uint16_t* getCalleeSavedRegs(const MachineFunction *MF = 0) + virtual const MCPhysReg* getCalleeSavedRegs(const MachineFunction *MF = 0) const = 0; /// getCallPreservedMask - Return a mask of call-preserved registers for the @@ -416,18 +432,6 @@ public: return MCRegisterInfo::getMatchingSuperReg(Reg, SubIdx, RC->MC); } - /// canCombineSubRegIndices - Given a register class and a list of - /// subregister indices, return true if it's possible to combine the - /// subregister indices into one that corresponds to a larger - /// subregister. Return the new subregister index by reference. Note the - /// new index may be zero if the given subregisters can be combined to - /// form the whole register. - virtual bool canCombineSubRegIndices(const TargetRegisterClass *RC, - SmallVectorImpl<unsigned> &SubIndices, - unsigned &NewSubIdx) const { - return 0; - } - /// getMatchingSuperRegClass - Return a subclass of the specified register /// class A so that each register in it has a sub-register of the /// specified sub-register index which is in the specified register class B. @@ -458,6 +462,8 @@ public: /// composeSubRegIndices - Return the subregister index you get from composing /// two subregister indices. /// + /// The special null sub-register index composes as the identity. + /// /// If R:a:b is the same register as R:c, then composeSubRegIndices(a, b) /// returns c. Note that composeSubRegIndices does not tell you about illegal /// compositions. If R does not have a subreg a, or R:a does not have a subreg @@ -467,11 +473,19 @@ public: /// ssub_0:S0 - ssub_3:S3 subregs. /// If you compose subreg indices dsub_1, ssub_0 you get ssub_2. /// - virtual unsigned composeSubRegIndices(unsigned a, unsigned b) const { - // This default implementation is correct for most targets. - return b; + unsigned composeSubRegIndices(unsigned a, unsigned b) const { + if (!a) return b; + if (!b) return a; + return composeSubRegIndicesImpl(a, b); } +protected: + /// Overridden by TableGen in targets that have sub-registers. + virtual unsigned composeSubRegIndicesImpl(unsigned, unsigned) const { + llvm_unreachable("Target has no sub-registers"); + } + +public: /// getCommonSuperRegClass - Find a common super-register class if it exists. /// /// Find a register class, SuperRC and two sub-register indices, PreA and @@ -566,10 +580,13 @@ public: return 0; } -// Get the weight in units of pressure for this register class. + /// Get the weight in units of pressure for this register class. virtual const RegClassWeight &getRegClassWeight( const TargetRegisterClass *RC) const = 0; + /// Get the weight in units of pressure for this register unit. + virtual unsigned getRegUnitWeight(unsigned RegUnit) const = 0; + /// Get the number of dimensions of register pressure. virtual unsigned getNumRegPressureSets() const = 0; @@ -585,27 +602,29 @@ public: virtual const int *getRegClassPressureSets( const TargetRegisterClass *RC) const = 0; - /// getRawAllocationOrder - Returns the register allocation order for a - /// specified register class with a target-dependent hint. The returned list - /// may contain reserved registers that cannot be allocated. - /// - /// Register allocators need only call this function to resolve - /// target-dependent hints, but it should work without hinting as well. - virtual ArrayRef<uint16_t> - getRawAllocationOrder(const TargetRegisterClass *RC, - unsigned HintType, unsigned HintReg, - const MachineFunction &MF) const { - return RC->getRawAllocationOrder(MF); - } - - /// ResolveRegAllocHint - Resolves the specified register allocation hint - /// to a physical register. Returns the physical register if it is successful. - virtual unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, - const MachineFunction &MF) const { - if (Type == 0 && Reg && isPhysicalRegister(Reg)) - return Reg; - return 0; - } + /// Get the dimensions of register pressure impacted by this register unit. + /// Returns a -1 terminated array of pressure set IDs. + virtual const int *getRegUnitPressureSets(unsigned RegUnit) const = 0; + + /// Get a list of 'hint' registers that the register allocator should try + /// first when allocating a physical register for the virtual register + /// VirtReg. These registers are effectively moved to the front of the + /// allocation order. + /// + /// The Order argument is the allocation order for VirtReg's register class + /// as returned from RegisterClassInfo::getOrder(). The hint registers must + /// come from Order, and they must not be reserved. + /// + /// The default implementation of this function can resolve + /// target-independent hints provided to MRI::setRegAllocationHint with + /// HintType == 0. Targets that override this function should defer to the + /// default implementation if they have no reason to change the allocation + /// order for VirtReg. There may be target-independent hints. + virtual void getRegAllocationHints(unsigned VirtReg, + ArrayRef<MCPhysReg> Order, + SmallVectorImpl<MCPhysReg> &Hints, + const MachineFunction &MF, + const VirtRegMap *VRM = 0) const; /// avoidWriteAfterWrite - Return true if the register allocator should avoid /// writing a register from RC in two consecutive instructions. @@ -848,7 +867,8 @@ class PrintReg { unsigned Reg; unsigned SubIdx; public: - PrintReg(unsigned reg, const TargetRegisterInfo *tri = 0, unsigned subidx = 0) + explicit PrintReg(unsigned reg, const TargetRegisterInfo *tri = 0, + unsigned subidx = 0) : TRI(tri), Reg(reg), SubIdx(subidx) {} void print(raw_ostream&) const; }; diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 4dc488d..0da82fd 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -10,25 +10,77 @@ // This file defines the target-independent scheduling interfaces which should // be implemented by each target which is using TableGen based scheduling. // +// The SchedMachineModel is defined by subtargets for three categories of data: +// 1. Basic properties for coarse grained instruction cost model. +// 2. Scheduler Read/Write resources for simple per-opcode cost model. +// 3. Instruction itineraties for detailed reservation tables. +// +// (1) Basic properties are defined by the SchedMachineModel +// class. Target hooks allow subtargets to associate opcodes with +// those properties. +// +// (2) A per-operand machine model can be implemented in any +// combination of the following ways: +// +// A. Associate per-operand SchedReadWrite types with Instructions by +// modifying the Instruction definition to inherit from Sched. For +// each subtarget, define WriteRes and ReadAdvance to associate +// processor resources and latency with each SchedReadWrite type. +// +// B. In each instruction definition, name an ItineraryClass. For each +// subtarget, define ItinRW entries to map ItineraryClass to +// per-operand SchedReadWrite types. Unlike method A, these types may +// be subtarget specific and can be directly associated with resources +// by defining SchedWriteRes and SchedReadAdvance. +// +// C. In the subtarget, map SchedReadWrite types to specific +// opcodes. This overrides any SchedReadWrite types or +// ItineraryClasses defined by the Instruction. As in method B, the +// subtarget can directly associate resources with SchedReadWrite +// types by defining SchedWriteRes and SchedReadAdvance. +// +// D. In either the target or subtarget, define SchedWriteVariant or +// SchedReadVariant to map one SchedReadWrite type onto another +// sequence of SchedReadWrite types. This allows dynamic selection of +// an instruction's machine model via custom C++ code. It also allows +// a machine-independent SchedReadWrite type to map to a sequence of +// machine-dependent types. +// +// (3) A per-pipeline-stage machine model can be implemented by providing +// Itineraries in addition to mapping instructions to ItineraryClasses. //===----------------------------------------------------------------------===// +// Include legacy support for instruction itineraries. include "llvm/Target/TargetItinerary.td" -// The SchedMachineModel is defined by subtargets for three categories of data: -// 1) Basic properties for coarse grained instruction cost model. -// 2) Scheduler Read/Write resources for simple per-opcode cost model. -// 3) Instruction itineraties for detailed reservation tables. +class Instruction; // Forward def + +// DAG operator that interprets the DAG args as Instruction defs. +def instrs; + +// DAG operator that interprets each DAG arg as a regex pattern for +// matching Instruction opcode names. +// The regex must match the beginning of the opcode (as in Python re.match). +// To avoid matching prefixes, append '$' to the pattern. +def instregex; + +// Define the SchedMachineModel and provide basic properties for +// coarse grained instruction cost model. Default values for the +// properties are defined in MCSchedModel. A value of "-1" in the +// target description's SchedMachineModel indicates that the property +// is not overriden by the target. // -// Default values for basic properties are defined in MCSchedModel. "-1" -// indicates that the property is not overriden by the target description. +// Target hooks allow subtargets to associate LoadLatency and +// HighLatency with groups of opcodes. class SchedMachineModel { - int IssueWidth = -1; // Max instructions that may be scheduled per cycle. + int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle. int MinLatency = -1; // Determines which instrucions are allowed in a group. // (-1) inorder (0) ooo, (1): inorder +var latencies. int LoadLatency = -1; // Cycles for loads to access the cache. int HighLatency = -1; // Approximation of cycles for "high latency" ops. int MispredictPenalty = -1; // Extra cycles for a mispredicted branch. + // Per-cycle resources tables. ProcessorItineraries Itineraries = NoItineraries; bit NoModel = 0; // Special tag to indicate missing machine model. @@ -38,4 +90,276 @@ def NoSchedModel : SchedMachineModel { let NoModel = 1; } -// TODO: Define classes for processor and scheduler resources. +// Define a kind of processor resource that may be common across +// similar subtargets. +class ProcResourceKind; + +// Define a number of interchangeable processor resources. NumUnits +// determines the throughput of instructions that require the resource. +// +// An optional Super resource may be given to model these resources as +// a subset of the more general super resources. Using one of these +// resources implies using one of the super resoruces. +// +// ProcResourceUnits normally model a few buffered resources within an +// out-of-order engine that the compiler attempts to conserve. +// Buffered resources may be held for multiple clock cycles, but the +// scheduler does not pin them to a particular clock cycle relative to +// instruction dispatch. Setting Buffered=0 changes this to an +// in-order resource. In this case, the scheduler counts down from the +// cycle that the instruction issues in-order, forcing an interlock +// with subsequent instructions that require the same resource until +// the number of ResourceCyles specified in WriteRes expire. +// +// SchedModel ties these units to a processor for any stand-alone defs +// of this class. Instances of subclass ProcResource will be automatically +// attached to a processor, so SchedModel is not needed. +class ProcResourceUnits<ProcResourceKind kind, int num> { + ProcResourceKind Kind = kind; + int NumUnits = num; + ProcResourceKind Super = ?; + bit Buffered = 1; + SchedMachineModel SchedModel = ?; +} + +// EponymousProcResourceKind helps implement ProcResourceUnits by +// allowing a ProcResourceUnits definition to reference itself. It +// should not be referenced anywhere else. +def EponymousProcResourceKind : ProcResourceKind; + +// Subtargets typically define processor resource kind and number of +// units in one place. +class ProcResource<int num> : ProcResourceKind, + ProcResourceUnits<EponymousProcResourceKind, num>; + +// A target architecture may define SchedReadWrite types and associate +// them with instruction operands. +class SchedReadWrite; + +// List the per-operand types that map to the machine model of an +// instruction. One SchedWrite type must be listed for each explicit +// def operand in order. Additional SchedWrite types may optionally be +// listed for implicit def operands. SchedRead types may optionally +// be listed for use operands in order. The order of defs relative to +// uses is insignificant. This way, the same SchedReadWrite list may +// be used for multiple forms of an operation. For example, a +// two-address instruction could have two tied operands or single +// operand that both reads and writes a reg. In both cases we have a +// single SchedWrite and single SchedRead in any order. +class Sched<list<SchedReadWrite> schedrw> { + list<SchedReadWrite> SchedRW = schedrw; +} + +// Define a scheduler resource associated with a def operand. +class SchedWrite : SchedReadWrite; +def NoWrite : SchedWrite; + +// Define a scheduler resource associated with a use operand. +class SchedRead : SchedReadWrite; + +// Define a SchedWrite that is modeled as a sequence of other +// SchedWrites with additive latency. This allows a single operand to +// be mapped the resources composed from a set of previously defined +// SchedWrites. +// +// If the final write in this sequence is a SchedWriteVariant marked +// Variadic, then the list of prior writes are distributed across all +// operands after resolving the predicate for the final write. +// +// SchedModel silences warnings but is ignored. +class WriteSequence<list<SchedWrite> writes, int rep = 1> : SchedWrite { + list<SchedWrite> Writes = writes; + int Repeat = rep; + SchedMachineModel SchedModel = ?; +} + +// Define values common to WriteRes and SchedWriteRes. +// +// SchedModel ties these resources to a processor. +class ProcWriteResources<list<ProcResourceKind> resources> { + list<ProcResourceKind> ProcResources = resources; + list<int> ResourceCycles = []; + int Latency = 1; + int NumMicroOps = 1; + bit BeginGroup = 0; + bit EndGroup = 0; + // Allow a processor to mark some scheduling classes as unsupported + // for stronger verification. + bit Unsupported = 0; + SchedMachineModel SchedModel = ?; +} + +// Define the resources and latency of a SchedWrite. This will be used +// directly by targets that have no itinerary classes. In this case, +// SchedWrite is defined by the target, while WriteResources is +// defined by the subtarget, and maps the SchedWrite to processor +// resources. +// +// If a target already has itinerary classes, SchedWriteResources can +// be used instead to define subtarget specific SchedWrites and map +// them to processor resources in one place. Then ItinRW can map +// itinerary classes to the subtarget's SchedWrites. +// +// ProcResources indicates the set of resources consumed by the write. +// Optionally, ResourceCycles indicates the number of cycles the +// resource is consumed. Each ResourceCycles item is paired with the +// ProcResource item at the same position in its list. Since +// ResourceCycles are rarely specialized, the list may be +// incomplete. By default, resources are consumed for a single cycle, +// regardless of latency, which models a fully pipelined processing +// unit. A value of 0 for ResourceCycles means that the resource must +// be available but is not consumed, which is only relevant for +// unbuffered resources. +// +// By default, each SchedWrite takes one micro-op, which is counted +// against the processor's IssueWidth limit. If an instruction can +// write multiple registers with a single micro-op, the subtarget +// should define one of the writes to be zero micro-ops. If a +// subtarget requires multiple micro-ops to write a single result, it +// should either override the write's NumMicroOps to be greater than 1 +// or require additional writes. Extra writes can be required either +// by defining a WriteSequence, or simply listing extra writes in the +// instruction's list of writers beyond the number of "def" +// operands. The scheduler assumes that all micro-ops must be +// dispatched in the same cycle. These micro-ops may be required to +// begin or end the current dispatch group. +class WriteRes<SchedWrite write, list<ProcResourceKind> resources> + : ProcWriteResources<resources> { + SchedWrite WriteType = write; +} + +// Directly name a set of WriteResources defining a new SchedWrite +// type at the same time. This class is unaware of its SchedModel so +// must be referenced by InstRW or ItinRW. +class SchedWriteRes<list<ProcResourceKind> resources> : SchedWrite, + ProcWriteResources<resources>; + +// Define values common to ReadAdvance and SchedReadAdvance. +// +// SchedModel ties these resources to a processor. +class ProcReadAdvance<int cycles, list<SchedWrite> writes = []> { + int Cycles = cycles; + list<SchedWrite> ValidWrites = writes; + // Allow a processor to mark some scheduling classes as unsupported + // for stronger verification. + bit Unsupported = 0; + SchedMachineModel SchedModel = ?; +} + +// A processor may define a ReadAdvance associated with a SchedRead +// to reduce latency of a prior write by N cycles. A negative advance +// effectively increases latency, which may be used for cross-domain +// stalls. +// +// A ReadAdvance may be associated with a list of SchedWrites +// to implement pipeline bypass. The Writes list may be empty to +// indicate operands that are always read this number of Cycles later +// than a normal register read, allowing the read's parent instruction +// to issue earlier relative to the writer. +class ReadAdvance<SchedRead read, int cycles, list<SchedWrite> writes = []> + : ProcReadAdvance<cycles, writes> { + SchedRead ReadType = read; +} + +// Directly associate a new SchedRead type with a delay and optional +// pipeline bypess. For use with InstRW or ItinRW. +class SchedReadAdvance<int cycles, list<SchedWrite> writes = []> : SchedRead, + ProcReadAdvance<cycles, writes>; + +// Define SchedRead defaults. Reads seldom need special treatment. +def ReadDefault : SchedRead; +def NoReadAdvance : SchedReadAdvance<0>; + +// Define shared code that will be in the same scope as all +// SchedPredicates. Available variables are: +// (const MachineInstr *MI, const TargetSchedModel *SchedModel) +class PredicateProlog<code c> { + code Code = c; +} + +// Define a predicate to determine which SchedVariant applies to a +// particular MachineInstr. The code snippet is used as an +// if-statement's expression. Available variables are MI, SchedModel, +// and anything defined in a PredicateProlog. +// +// SchedModel silences warnings but is ignored. +class SchedPredicate<code pred> { + SchedMachineModel SchedModel = ?; + code Predicate = pred; +} +def NoSchedPred : SchedPredicate<[{true}]>; + +// Associate a predicate with a list of SchedReadWrites. By default, +// the selected SchedReadWrites are still associated with a single +// operand and assumed to execute sequentially with additive +// latency. However, if the parent SchedWriteVariant or +// SchedReadVariant is marked "Variadic", then each Selected +// SchedReadWrite is mapped in place to the instruction's variadic +// operands. In this case, latency is not additive. If the current Variant +// is already part of a Sequence, then that entire chain leading up to +// the Variant is distributed over the variadic operands. +class SchedVar<SchedPredicate pred, list<SchedReadWrite> selected> { + SchedPredicate Predicate = pred; + list<SchedReadWrite> Selected = selected; +} + +// SchedModel silences warnings but is ignored. +class SchedVariant<list<SchedVar> variants> { + list<SchedVar> Variants = variants; + bit Variadic = 0; + SchedMachineModel SchedModel = ?; +} + +// A SchedWriteVariant is a single SchedWrite type that maps to a list +// of SchedWrite types under the conditions defined by its predicates. +// +// A Variadic write is expanded to cover multiple "def" operands. The +// SchedVariant's Expansion list is then interpreted as one write +// per-operand instead of the usual sequential writes feeding a single +// operand. +class SchedWriteVariant<list<SchedVar> variants> : SchedWrite, + SchedVariant<variants> { +} + +// A SchedReadVariant is a single SchedRead type that maps to a list +// of SchedRead types under the conditions defined by its predicates. +// +// A Variadic write is expanded to cover multiple "readsReg" operands as +// explained above. +class SchedReadVariant<list<SchedVar> variants> : SchedRead, + SchedVariant<variants> { +} + +// Map a set of opcodes to a list of SchedReadWrite types. This allows +// the subtarget to easily override specific operations. +// +// SchedModel ties this opcode mapping to a processor. +class InstRW<list<SchedReadWrite> rw, dag instrlist> { + list<SchedReadWrite> OperandReadWrites = rw; + dag Instrs = instrlist; + SchedMachineModel SchedModel = ?; +} + +// Map a set of itinerary classes to SchedReadWrite resources. This is +// used to bootstrap a target (e.g. ARM) when itineraries already +// exist and changing InstrInfo is undesirable. +// +// SchedModel ties this ItineraryClass mapping to a processor. +class ItinRW<list<SchedReadWrite> rw, list<InstrItinClass> iic> { + list<InstrItinClass> MatchedItinClasses = iic; + list<SchedReadWrite> OperandReadWrites = rw; + SchedMachineModel SchedModel = ?; +} + +// Alias a target-defined SchedReadWrite to a processor specific +// SchedReadWrite. This allows a subtarget to easily map a +// SchedReadWrite type onto a WriteSequence, SchedWriteVariant, or +// SchedReadVariant. +// +// SchedModel will usually be provided by surrounding let statement +// and ties this SchedAlias mapping to a processor. +class SchedAlias<SchedReadWrite match, SchedReadWrite alias> { + SchedReadWrite MatchRW = match; + SchedReadWrite AliasRW = alias; + SchedMachineModel SchedModel = ?; +} diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index c9ca722..96793bc 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -20,7 +20,7 @@ namespace llvm { -class TargetData; +class DataLayout; class TargetMachine; //===----------------------------------------------------------------------===// @@ -28,13 +28,13 @@ class TargetMachine; /// SelectionDAG lowering and instruction selection process. /// class TargetSelectionDAGInfo { - TargetSelectionDAGInfo(const TargetSelectionDAGInfo &); // DO NOT IMPLEMENT - void operator=(const TargetSelectionDAGInfo &); // DO NOT IMPLEMENT + TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION; + void operator=(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION; - const TargetData *TD; + const DataLayout *TD; protected: - const TargetData *getTargetData() const { return TD; } + const DataLayout *getDataLayout() const { return TD; } public: explicit TargetSelectionDAGInfo(const TargetMachine &TM); diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index fc23b2c..3f22f47 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -19,9 +19,11 @@ namespace llvm { +class MachineInstr; class SDep; class SUnit; class TargetRegisterClass; +class TargetSchedModel; template <typename T> class SmallVectorImpl; //===----------------------------------------------------------------------===// @@ -31,8 +33,8 @@ template <typename T> class SmallVectorImpl; /// be exposed through a TargetSubtargetInfo-derived class. /// class TargetSubtargetInfo : public MCSubtargetInfo { - TargetSubtargetInfo(const TargetSubtargetInfo&); // DO NOT IMPLEMENT - void operator=(const TargetSubtargetInfo&); // DO NOT IMPLEMENT + TargetSubtargetInfo(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION; + void operator=(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION; protected: // Can only create subclasses... TargetSubtargetInfo(); public: @@ -43,23 +45,33 @@ public: virtual ~TargetSubtargetInfo(); - /// getSpecialAddressLatency - For targets where it is beneficial to - /// backschedule instructions that compute addresses, return a value - /// indicating the number of scheduling cycles of backscheduling that - /// should be attempted. - virtual unsigned getSpecialAddressLatency() const { return 0; } + /// Resolve a SchedClass at runtime, where SchedClass identifies an + /// MCSchedClassDesc with the isVariant property. This may return the ID of + /// another variant SchedClass, but repeated invocation must quickly terminate + /// in a nonvariant SchedClass. + virtual unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *MI, + const TargetSchedModel* SchedModel) const { + return 0; + } + + /// \brief True if the subtarget should run MachineScheduler after aggressive + /// coalescing. + /// + /// This currently replaces the SelectionDAG scheduler with the "source" order + /// scheduler. It does not yet disable the postRA scheduler. + virtual bool enableMachineScheduler() 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 // CriticalPathRCs return any register classes that should only be broken - // if on the critical path. + // if on the critical path. virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const; // adjustSchedDependency - Perform target specific adjustments to // the latency of a schedule dependency. - virtual void adjustSchedDependency(SUnit *def, SUnit *use, + virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep& dep) const { } }; diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index 18176e8..e6eb8d3 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -15,7 +15,7 @@ #ifndef LLVM_TRANSFORMS_IPO_H #define LLVM_TRANSFORMS_IPO_H -#include <vector> +#include "llvm/ADT/ArrayRef.h" namespace llvm { @@ -104,23 +104,14 @@ Pass *createPruneEHPass(); //===----------------------------------------------------------------------===// /// createInternalizePass - This pass loops over all of the functions in the -/// input module, internalizing all globals (functions and variables) not part -/// of the api. If a list of symbols is specified with the -/// -internalize-public-api-* command line options, those symbols are not -/// internalized and all others are. Otherwise if AllButMain is set and the -/// main function is found, all other globals are marked as internal. If no api -/// is supplied and AllButMain is not set, or no main function is found, nothing -/// is internalized. -/// -ModulePass *createInternalizePass(bool AllButMain); - -/// createInternalizePass - This pass loops over all of the functions in the /// input module, internalizing all globals (functions and variables) not in the /// given exportList. /// /// Note that commandline options that are used with the above function are not -/// used now! Also, when exportList is empty, nothing is internalized. -ModulePass *createInternalizePass(const std::vector<const char *> &exportList); +/// used now! +ModulePass *createInternalizePass(ArrayRef<const char *> exportList); +/// createInternalizePass - Same as above, but with an empty exportList. +ModulePass *createInternalizePass(); //===----------------------------------------------------------------------===// /// createDeadArgEliminationPass - This pass removes arguments from functions @@ -192,6 +183,16 @@ ModulePass *createMergeFunctionsPass(); /// createPartialInliningPass - This pass inlines parts of functions. /// ModulePass *createPartialInliningPass(); + +//===----------------------------------------------------------------------===// +// createMetaRenamerPass - Rename everything with metasyntatic names. +// +ModulePass *createMetaRenamerPass(); + +//===----------------------------------------------------------------------===// +/// createBarrierNoopPass - This pass is purely a module pass barrier in a pass +/// manager. +ModulePass *createBarrierNoopPass(); } // End llvm namespace diff --git a/include/llvm/Transforms/IPO/InlinerPass.h b/include/llvm/Transforms/IPO/InlinerPass.h index 7c3cfc8..43a0ac8 100644 --- a/include/llvm/Transforms/IPO/InlinerPass.h +++ b/include/llvm/Transforms/IPO/InlinerPass.h @@ -17,11 +17,11 @@ #ifndef LLVM_TRANSFORMS_IPO_INLINERPASS_H #define LLVM_TRANSFORMS_IPO_INLINERPASS_H -#include "llvm/CallGraphSCCPass.h" +#include "llvm/Analysis/CallGraphSCCPass.h" namespace llvm { class CallSite; - class TargetData; + class DataLayout; class InlineCost; template<class PtrType, unsigned SmallSize> class SmallPtrSet; @@ -42,6 +42,7 @@ struct Inliner : public CallGraphSCCPass { // Pass class. virtual bool runOnSCC(CallGraphSCC &SCC); + using llvm::Pass::doFinalization; // doFinalization - Remove now-dead linkonce functions at the end of // processing to avoid breaking the SCC traversal. virtual bool doFinalization(CallGraph &CG); diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 47ce902..3ea0a42 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -104,6 +104,7 @@ public: bool DisableUnitAtATime; bool DisableUnrollLoops; bool Vectorize; + bool LoopVectorize; 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 4b0c448..5504dc9 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -14,6 +14,8 @@ #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_H #define LLVM_TRANSFORMS_INSTRUMENTATION_H +#include "llvm/ADT/StringRef.h" + namespace llvm { class ModulePass; @@ -31,19 +33,27 @@ ModulePass *createPathProfilerPass(); // Insert GCOV profiling instrumentation ModulePass *createGCOVProfilerPass(bool EmitNotes = true, bool EmitData = true, bool Use402Format = false, - bool UseExtraChecksum = false); + bool UseExtraChecksum = false, + bool NoRedZone = false); // Insert AddressSanitizer (address sanity checking) instrumentation -ModulePass *createAddressSanitizerPass(); +FunctionPass *createAddressSanitizerFunctionPass( + bool CheckInitOrder = false, bool CheckUseAfterReturn = false, + bool CheckLifetime = false, StringRef BlacklistFile = StringRef()); +ModulePass *createAddressSanitizerModulePass( + bool CheckInitOrder = false, StringRef BlacklistFile = StringRef()); + +// Insert MemorySanitizer instrumentation (detection of uninitialized reads) +FunctionPass *createMemorySanitizerPass(bool TrackOrigins = false, + StringRef BlacklistFile = StringRef()); + // Insert ThreadSanitizer (race detection) instrumentation -FunctionPass *createThreadSanitizerPass(); +FunctionPass *createThreadSanitizerPass(StringRef BlacklistFile = StringRef()); // BoundsChecking - This pass instruments the code to perform run-time bounds // checking on loads, stores, and other memory intrinsics. -// Penalty is the maximum run-time that is acceptable for the user. -// -FunctionPass *createBoundsCheckingPass(unsigned Penalty = 5); +FunctionPass *createBoundsCheckingPass(); } // End llvm namespace diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 3dce6fe..d465127 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -70,6 +70,12 @@ FunctionPass *createAggressiveDCEPass(); //===----------------------------------------------------------------------===// // +// SROA - Replace aggregates or pieces of aggregates with scalar SSA values. +// +FunctionPass *createSROAPass(bool RequiresDomTree = true); + +//===----------------------------------------------------------------------===// +// // ScalarReplAggregates - Break up alloca's of aggregates into multiple allocas // if possible. // @@ -109,11 +115,9 @@ Pass *createLICMPass(); //===----------------------------------------------------------------------===// // // LoopStrengthReduce - This pass is strength reduces GEP instructions that use -// a loop's canonical induction variable as one of their indices. It takes an -// optional parameter used to consult the target machine whether certain -// transformations are profitable. +// a loop's canonical induction variable as one of their indices. // -Pass *createLoopStrengthReducePass(const TargetLowering *TLI = 0); +Pass *createLoopStrengthReducePass(); Pass *createGlobalMergePass(const TargetLowering *TLI = 0); diff --git a/include/llvm/Transforms/Utils/AddrModeMatcher.h b/include/llvm/Transforms/Utils/AddrModeMatcher.h deleted file mode 100644 index 90485eb..0000000 --- a/include/llvm/Transforms/Utils/AddrModeMatcher.h +++ /dev/null @@ -1,108 +0,0 @@ -//===- AddrModeMatcher.h - Addressing mode matching facility ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// AddressingModeMatcher - This class exposes a single public method, which is -// used to construct a "maximal munch" of the addressing mode for the target -// specified by TLI for an access to "V" with an access type of AccessTy. This -// returns the addressing mode that is actually matched by value, but also -// returns the list of instructions involved in that addressing computation in -// AddrModeInsts. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_UTILS_ADDRMODEMATCHER_H -#define LLVM_TRANSFORMS_UTILS_ADDRMODEMATCHER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Target/TargetLowering.h" - -namespace llvm { - -class GlobalValue; -class Instruction; -class Value; -class Type; -class User; -class raw_ostream; - -/// ExtAddrMode - This is an extended version of TargetLowering::AddrMode -/// which holds actual Value*'s for register values. -struct ExtAddrMode : public TargetLowering::AddrMode { - Value *BaseReg; - Value *ScaledReg; - ExtAddrMode() : BaseReg(0), ScaledReg(0) {} - void print(raw_ostream &OS) const; - void dump() const; - - bool operator==(const ExtAddrMode& O) const { - return (BaseReg == O.BaseReg) && (ScaledReg == O.ScaledReg) && - (BaseGV == O.BaseGV) && (BaseOffs == O.BaseOffs) && - (HasBaseReg == O.HasBaseReg) && (Scale == O.Scale); - } -}; - -static inline raw_ostream &operator<<(raw_ostream &OS, const ExtAddrMode &AM) { - AM.print(OS); - return OS; -} - -class AddressingModeMatcher { - SmallVectorImpl<Instruction*> &AddrModeInsts; - const TargetLowering &TLI; - - /// AccessTy/MemoryInst - This is the type for the access (e.g. double) and - /// the memory instruction that we're computing this address for. - Type *AccessTy; - Instruction *MemoryInst; - - /// AddrMode - This is the addressing mode that we're building up. This is - /// part of the return value of this addressing mode matching stuff. - ExtAddrMode &AddrMode; - - /// IgnoreProfitability - This is set to true when we should not do - /// profitability checks. When true, IsProfitableToFoldIntoAddressingMode - /// always returns true. - bool IgnoreProfitability; - - AddressingModeMatcher(SmallVectorImpl<Instruction*> &AMI, - const TargetLowering &T, Type *AT, - Instruction *MI, ExtAddrMode &AM) - : AddrModeInsts(AMI), TLI(T), AccessTy(AT), MemoryInst(MI), AddrMode(AM) { - IgnoreProfitability = false; - } -public: - - /// Match - Find the maximal addressing mode that a load/store of V can fold, - /// give an access type of AccessTy. This returns a list of involved - /// instructions in AddrModeInsts. - static ExtAddrMode Match(Value *V, Type *AccessTy, - Instruction *MemoryInst, - SmallVectorImpl<Instruction*> &AddrModeInsts, - const TargetLowering &TLI) { - ExtAddrMode Result; - - bool Success = - AddressingModeMatcher(AddrModeInsts, TLI, AccessTy, - MemoryInst, Result).MatchAddr(V, 0); - (void)Success; assert(Success && "Couldn't select *anything*?"); - return Result; - } -private: - bool MatchScaledValue(Value *ScaleReg, int64_t Scale, unsigned Depth); - bool MatchAddr(Value *V, unsigned Depth); - bool MatchOperationAddr(User *Operation, unsigned Opcode, unsigned Depth); - bool IsProfitableToFoldIntoAddressingMode(Instruction *I, - ExtAddrMode &AMBefore, - ExtAddrMode &AMAfter); - bool ValueAlreadyLiveAtInst(Value *Val, Value *KnownLive1, Value *KnownLive2); -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 2510aec..d08f75e 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -17,7 +17,7 @@ // FIXME: Move to this file: BasicBlock::removePredecessor, BB::splitBasicBlock -#include "llvm/BasicBlock.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/Support/CFG.h" #include "llvm/Support/DebugLoc.h" @@ -25,9 +25,11 @@ namespace llvm { class AliasAnalysis; class Instruction; +class MDNode; class Pass; class ReturnInst; class TargetLibraryInfo; +class TerminatorInst; /// DeleteDeadBlock - Delete the specified block, which must have no /// predecessors. @@ -203,6 +205,29 @@ void SplitLandingPadPredecessors(BasicBlock *OrigBB,ArrayRef<BasicBlock*> Preds, ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, BasicBlock *Pred); +/// SplitBlockAndInsertIfThen - Split the containing block at the +/// specified instruction - everything before and including Cmp stays +/// in the old basic block, and everything after Cmp is moved to a +/// new block. The two blocks are connected by a conditional branch +/// (with value of Cmp being the condition). +/// Before: +/// Head +/// Cmp +/// Tail +/// After: +/// Head +/// Cmp +/// if (Cmp) +/// ThenBlock +/// Tail +/// +/// If Unreachable is true, then ThenBlock ends with +/// UnreachableInst, otherwise it branches to Tail. +/// Returns the NewBasicBlock's terminator. + +TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp, + bool Unreachable, MDNode *BranchWeights = 0); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index a6e41f0..ca2d8f6 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -15,11 +15,11 @@ #ifndef TRANSFORMS_UTILS_BUILDLIBCALLS_H #define TRANSFORMS_UTILS_BUILDLIBCALLS_H -#include "llvm/IRBuilder.h" +#include "llvm/IR/IRBuilder.h" namespace llvm { class Value; - class TargetData; + class DataLayout; class TargetLibraryInfo; /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. @@ -28,52 +28,52 @@ namespace llvm { /// EmitStrLen - Emit a call to the strlen function to the builder, for the /// specified pointer. Ptr is required to be some pointer type, and the /// return value has 'intptr_t' type. - Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD, + Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitStrNLen - Emit a call to the strnlen function to the builder, for the /// specified pointer. Ptr is required to be some pointer type, MaxLen must /// be of size_t type, and the return value has 'intptr_t' type. Value *EmitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI); + const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitStrChr - Emit a call to the strchr function to the builder, for the /// specified pointer and character. Ptr is required to be some pointer type, /// and the return value has 'i8*' type. - Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const TargetData *TD, + Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitStrNCmp - Emit a call to the strncmp function to the builder. Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI); + const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the /// specified pointer arguments. Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI, + const DataLayout *TD, const TargetLibraryInfo *TLI, StringRef Name = "strcpy"); /// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the /// specified pointer arguments and length. Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI, + const DataLayout *TD, const TargetLibraryInfo *TLI, StringRef Name = "strncpy"); /// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder. /// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src /// are pointers. Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, - IRBuilder<> &B, const TargetData *TD, + IRBuilder<> &B, const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI); + const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitMemCmp - Emit a call to the memcmp function. Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI); + const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' /// (e.g. 'floor'). This function is known to take a single of type matching @@ -81,32 +81,32 @@ namespace llvm { /// 'l' is added as the suffix of name, if 'Op' is a float, we add a 'f' /// suffix. Value *EmitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, - const AttrListPtr &Attrs); + const AttributeSet &Attrs); /// EmitPutChar - Emit a call to the putchar function. This assumes that Char /// is an integer. - Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD, + Value *EmitPutChar(Value *Char, IRBuilder<> &B, const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitPutS - Emit a call to the puts function. This assumes that Str is /// some pointer. - Value *EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD, + Value *EmitPutS(Value *Str, IRBuilder<> &B, const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitFPutC - Emit a call to the fputc function. This assumes that Char is /// an i32, and File is a pointer to FILE. Value *EmitFPutC(Value *Char, Value *File, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI); + const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitFPutS - Emit a call to the puts function. Str is required to be a /// pointer and File is a pointer to FILE. - Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const TargetData *TD, + Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const DataLayout *TD, const TargetLibraryInfo *TLI); /// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI); + const DataLayout *TD, const TargetLibraryInfo *TLI); /// SimplifyFortifiedLibCalls - Helper class for folding checked library /// calls (e.g. __strcpy_chk) into their unchecked counterparts. @@ -118,7 +118,7 @@ namespace llvm { bool isString) const = 0; public: virtual ~SimplifyFortifiedLibCalls(); - bool fold(CallInst *CI, const TargetData *TD, const TargetLibraryInfo *TLI); + bool fold(CallInst *CI, const DataLayout *TD, const TargetLibraryInfo *TLI); }; } diff --git a/include/llvm/Transforms/Utils/BypassSlowDivision.h b/include/llvm/Transforms/Utils/BypassSlowDivision.h index c262434..b11be05 100644 --- a/include/llvm/Transforms/Utils/BypassSlowDivision.h +++ b/include/llvm/Transforms/Utils/BypassSlowDivision.h @@ -18,7 +18,8 @@ #ifndef TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H #define TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H -#include "llvm/Function.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/Function.h" namespace llvm { @@ -26,7 +27,7 @@ namespace llvm { /// profitably bypassed and carried out with a shorter, faster divide. bool bypassSlowDivision(Function &F, Function::iterator &I, - const DenseMap<Type *, Type *> &BypassTypeMap); + const DenseMap<unsigned int, unsigned int> &BypassWidth); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index b7b5d29..14212f6 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -18,9 +18,9 @@ #ifndef LLVM_TRANSFORMS_UTILS_CLONING_H #define LLVM_TRANSFORMS_UTILS_CLONING_H -#include "llvm/ADT/ValueMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/ValueMap.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Transforms/Utils/ValueMapper.h" @@ -39,7 +39,7 @@ class ReturnInst; class CallSite; class Trace; class CallGraph; -class TargetData; +class DataLayout; class Loop; class LoopInfo; class AllocaInst; @@ -116,13 +116,6 @@ Function *CloneFunction(const Function *F, bool ModuleLevelChanges, ClonedCodeInfo *CodeInfo = 0); -/// CloneFunction - Version of the function that doesn't need the VMap. -/// -inline Function *CloneFunction(const Function *F, ClonedCodeInfo *CodeInfo = 0){ - ValueToValueMapTy VMap; - return CloneFunction(F, VMap, CodeInfo); -} - /// Clone OldFunc into NewFunc, transforming the old arguments into references /// to VMap values. Note that if NewFunc already has basic blocks, the ones /// cloned into it will be added to the end of the function. This function @@ -157,7 +150,7 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, SmallVectorImpl<ReturnInst*> &Returns, const char *NameSuffix = "", ClonedCodeInfo *CodeInfo = 0, - const TargetData *TD = 0, + const DataLayout *TD = 0, Instruction *TheCall = 0); @@ -165,13 +158,13 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, /// InlineFunction call, and records the auxiliary results produced by it. class InlineFunctionInfo { public: - explicit InlineFunctionInfo(CallGraph *cg = 0, const TargetData *td = 0) + explicit InlineFunctionInfo(CallGraph *cg = 0, const DataLayout *td = 0) : CG(cg), TD(td) {} /// CG - If non-null, InlineFunction will update the callgraph to reflect the /// changes it makes. CallGraph *CG; - const TargetData *TD; + const DataLayout *TD; /// StaticAllocas - InlineFunction fills this in with all static allocas that /// get copied into the caller. diff --git a/include/llvm/Transforms/Utils/CmpInstAnalysis.h b/include/llvm/Transforms/Utils/CmpInstAnalysis.h index 7ad7bdd..488d7a5 100644 --- a/include/llvm/Transforms/Utils/CmpInstAnalysis.h +++ b/include/llvm/Transforms/Utils/CmpInstAnalysis.h @@ -15,7 +15,7 @@ #ifndef LLVM_TRANSFORMS_UTILS_CMPINSTANALYSIS_H #define LLVM_TRANSFORMS_UTILS_CMPINSTANALYSIS_H -#include "llvm/InstrTypes.h" +#include "llvm/IR/InstrTypes.h" namespace llvm { class ICmpInst; diff --git a/include/llvm/Transforms/Utils/IntegerDivision.h b/include/llvm/Transforms/Utils/IntegerDivision.h new file mode 100644 index 0000000..cecc807 --- /dev/null +++ b/include/llvm/Transforms/Utils/IntegerDivision.h @@ -0,0 +1,48 @@ +//===- llvm/Transforms/Utils/IntegerDivision.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 contains an implementation of 32bit integer division for targets +// that don't have native support. It's largely derived from compiler-rt's +// implementation of __udivsi3, but hand-tuned for targets that prefer less +// control flow. +// +//===----------------------------------------------------------------------===// + +#ifndef TRANSFORMS_UTILS_INTEGERDIVISION_H +#define TRANSFORMS_UTILS_INTEGERDIVISION_H + +namespace llvm { + class BinaryOperator; +} + +namespace llvm { + + /// Generate code to calculate the remainder of two integers, replacing Rem + /// with the generated code. This currently generates code using the udiv + /// expansion, but future work includes generating more specialized code, + /// e.g. when more information about the operands are known. Currently only + /// implements 32bit scalar division (due to udiv's limitation), but future + /// work is removing this limitation. + /// + /// @brief Replace Rem with generated code. + bool expandRemainder(BinaryOperator *Rem); + + /// Generate code to divide two integers, replacing Div with the generated + /// code. This currently generates code similarly to compiler-rt's + /// implementations, but future work includes generating more specialized code + /// when more information about the operands are known. Currently only + /// implements 32bit scalar division, but future work is removing this + /// limitation. + /// + /// @brief Replace Div with generated code. + bool expandDivision(BinaryOperator* Div); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 83f0e7a..687c9d5 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -15,10 +15,10 @@ #ifndef LLVM_TRANSFORMS_UTILS_LOCAL_H #define LLVM_TRANSFORMS_UTILS_LOCAL_H -#include "llvm/IRBuilder.h" -#include "llvm/Operator.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Operator.h" #include "llvm/Support/GetElementPtrTypeIterator.h" -#include "llvm/Target/TargetData.h" namespace llvm { @@ -35,8 +35,9 @@ class Pass; class PHINode; class AllocaInst; class ConstantExpr; -class TargetData; +class DataLayout; class TargetLibraryInfo; +class TargetTransformInfo; class DIBuilder; template<typename T> class SmallVectorImpl; @@ -84,7 +85,7 @@ bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=0); /// /// This returns true if it changed the code, note that it can delete /// instructions in other blocks as well in this block. -bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD = 0, +bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0); //===----------------------------------------------------------------------===// @@ -103,7 +104,7 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD = 0, /// .. and delete the predecessor corresponding to the '1', this will attempt to /// recursively fold the 'and' to 0. void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, - TargetData *TD = 0); + DataLayout *TD = 0); /// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its @@ -134,7 +135,8 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB); /// of the CFG. It returns true if a modification was made, possibly deleting /// the basic block that was pointed to. /// -bool SimplifyCFG(BasicBlock *BB, const TargetData *TD = 0); +bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, + const DataLayout *TD = 0); /// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch, /// and if a predecessor branches to us and one of our successors, fold the @@ -162,10 +164,10 @@ AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0); /// and it is more than the alignment of the ultimate object, see if we can /// increase the alignment of the ultimate object, making this check succeed. unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, - const TargetData *TD = 0); + const DataLayout *TD = 0); /// getKnownAlignment - Try to infer an alignment for the specified pointer. -static inline unsigned getKnownAlignment(Value *V, const TargetData *TD = 0) { +static inline unsigned getKnownAlignment(Value *V, const DataLayout *TD = 0) { return getOrEnforceKnownAlignment(V, 0, TD); } @@ -175,7 +177,7 @@ static inline unsigned getKnownAlignment(Value *V, const TargetData *TD = 0) { /// When NoAssumptions is true, no assumptions about index computation not /// overflowing is made. template<typename IRBuilderTy> -Value *EmitGEPOffset(IRBuilderTy *Builder, const TargetData &TD, User *GEP, +Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP, bool NoAssumptions = false) { gep_type_iterator GTI = gep_type_begin(GEP); Type *IntPtrTy = TD.getIntPtrType(GEP->getContext()); @@ -250,6 +252,16 @@ bool LowerDbgDeclare(Function &F); /// an alloca, if any. DbgDeclareInst *FindAllocaDbgDeclare(Value *V); +/// replaceDbgDeclareForAlloca - Replaces llvm.dbg.declare instruction when +/// alloca is replaced with a new value. +bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, + DIBuilder &Builder); + +/// \brief Remove all blocks that can not be reached from the function's entry. +/// +/// Returns true if any basic block was removed. +bool removeUnreachableBlocks(Function &F); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h index 4c82149..cd04893 100644 --- a/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/include/llvm/Transforms/Utils/SSAUpdater.h @@ -15,6 +15,7 @@ #define LLVM_TRANSFORMS_UTILS_SSAUPDATER_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" namespace llvm { class BasicBlock; @@ -109,8 +110,8 @@ public: private: Value *GetValueAtEndOfBlockInternal(BasicBlock *BB); - void operator=(const SSAUpdater&); // DO NOT IMPLEMENT - SSAUpdater(const SSAUpdater&); // DO NOT IMPLEMENT + void operator=(const SSAUpdater&) LLVM_DELETED_FUNCTION; + SSAUpdater(const SSAUpdater&) LLVM_DELETED_FUNCTION; }; /// LoadAndStorePromoter - This little helper class provides a convenient way to diff --git a/include/llvm/Transforms/Utils/SimplifyIndVar.h b/include/llvm/Transforms/Utils/SimplifyIndVar.h index 2632d18..7e97e21 100644 --- a/include/llvm/Transforms/Utils/SimplifyIndVar.h +++ b/include/llvm/Transforms/Utils/SimplifyIndVar.h @@ -21,8 +21,6 @@ namespace llvm { -extern cl::opt<bool> DisableIVRewrite; - class CastInst; class IVUsers; class Loop; diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h new file mode 100644 index 0000000..6bb81be --- /dev/null +++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -0,0 +1,53 @@ +//===- SimplifyLibCalls.h - Library call simplifier -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an interface to build some C language libcalls for +// optimization passes that need to call the various functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H +#define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H + +namespace llvm { + class Value; + class CallInst; + class DataLayout; + class Instruction; + class TargetLibraryInfo; + class LibCallSimplifierImpl; + + /// LibCallSimplifier - This class implements a collection of optimizations + /// that replace well formed calls to library functions with a more optimal + /// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'. + class LibCallSimplifier { + /// Impl - A pointer to the actual implementation of the library call + /// simplifier. + LibCallSimplifierImpl *Impl; + public: + LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI, + bool UnsafeFPShrink); + virtual ~LibCallSimplifier(); + + /// optimizeCall - Take the given call instruction and return a more + /// optimal value to replace the instruction with or 0 if a more + /// optimal form can't be found. Note that the returned value may + /// be equal to the instruction being optimized. In this case all + /// other instructions that use the given instruction were modified + /// and the given instruction is dead. + Value *optimizeCall(CallInst *CI); + + /// replaceAllUsesWith - This method is used when the library call + /// simplifier needs to replace instructions other than the library + /// call being modified. + virtual void replaceAllUsesWith(Instruction *I, Value *With) const; + }; +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h index 8594707..5390c5e 100644 --- a/include/llvm/Transforms/Utils/ValueMapper.h +++ b/include/llvm/Transforms/Utils/ValueMapper.h @@ -25,7 +25,7 @@ namespace llvm { /// ValueMapTypeRemapper - This is a class that can be implemented by clients /// to remap types when cloning constants and instructions. class ValueMapTypeRemapper { - virtual void Anchor(); // Out of line method. + virtual void anchor(); // Out of line method. public: virtual ~ValueMapTypeRemapper() {} diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h index 1e49a9c..1ba4d22 100644 --- a/include/llvm/Transforms/Vectorize.h +++ b/include/llvm/Transforms/Vectorize.h @@ -18,6 +18,7 @@ namespace llvm { class BasicBlock; class BasicBlockPass; +class Pass; //===----------------------------------------------------------------------===// /// @brief Vectorize configuration. @@ -107,6 +108,12 @@ BasicBlockPass * createBBVectorizePass(const VectorizeConfig &C = VectorizeConfig()); //===----------------------------------------------------------------------===// +// +// LoopVectorize - Create a loop vectorization pass. +// +Pass *createLoopVectorizePass(); + +//===----------------------------------------------------------------------===// /// @brief Vectorize the BasicBlock. /// /// @param BB The BasicBlock to be vectorized |
